天天看點

【原創】rabbitmq-c源碼分析之amqp_socket.c

     走讀 amqp_socket.c 源碼,發現若幹值得注意的細節:

【amqp_open_socket 】

在 amqp_open_socket 函數中通過 getaddrinfo 函數進行域名解析可能會産生阻塞。其中參數指定了

<a href="http://my.oschina.net/moooofly/blog/104798#">?</a>

1

2

3

4

5

6

<code>struct</code> <code>addrinfo hint;</code>

<code>...</code>

<code>hint.ai_family = pf_unspec;</code><code>/* pf_inet or pf_inet6 */</code>

<code>hint.ai_socktype = sock_stream;</code>

<code>hint.ai_protocol = ipproto_tcp;</code>

故其會對ipv4和ipv6位址均進行查詢。

建立 socket 時的代碼表明,其根據實際情況(ipv4或ipv6)建立對應的socket。

<code>sockfd = (</code><code>int</code><code>)socket(addr-&gt;ai_family, addr-&gt;ai_socktype, addr-&gt;ai_protocol);</code>

socket 建立後僅設定了 so_nosigpipe(該辨別僅在 ios 系統下有效) 和 tcp_nodelay 選項,之後就進行了 connect 動作,說明該 socket 為阻塞式用法,并且未綁定本地任何位址。這樣的結果是 connect 會根據連接配接到的對端位址自動綁定本地對應位址。

另外,由于處理的是阻塞式 socket ,故 connect 僅對出錯傳回進行了簡單處理。唯一可能需要注意的,實作中沒有 connect 重連機制,直接結果是對每一個位址僅嘗試 connect 一次。

【amqp_send_header】

該函數僅需看一下 send 函數的 flags 即可。

<code>send(state-&gt;sockfd, (</code><code>void</code> <code>*)header, 8, msg_nosignal);</code>

設定 send 函數第三個參數為 msg_nosignal ,即要求程序不把信号 sigpipe 發送給系統,而輸出到終端。

【sasl_method_name】

該函數說明 rabbitmq-c 僅支援 plain sasl ,其餘擴充需要自己實作。

【sasl_response】

沒啥好說的,隻有 response_buf 的内容拼接格式看下就可以。

【wait_frame_inner】

該函數是目前 c 檔案最核心的一個。其中包含了用于幀資料解析和生成的 amqp_handle_input 函數,以及用于接收資料 recv 函數。其中 recv 是阻塞點。在 sockfd 上收到的資料先緩存在 sock_inbound_buffer 中,随後會在 while 循環中按協定,逐個按幀解析出來,傳回給上層。此代碼寫的挺精巧,可以學習借鑒。

【amqp_simple_wait_frame】

此函數是對 wait_frame_inner 的封裝,并增加了對幀連結清單的檢測和處理。意思是隻要幀連結清單中還有資料待處理就先把其中的資料取出來處理,否則通過 wait_frame_inner 接收幀後再處理。

【amqp_simple_wait_method】

此函數是對 amqp_simple_wait_frame 的封裝,并增加了對幀的内容的檢測和處理。

【amqp_send_method】

構造待發送幀的内容,内部使用 amqp_send_frame 來發送實際的幀資料。

【amqp_simple_rpc】

該函數是另一個需要留意的點。其内部通過調用 amqp_send_method 和 wait_frame_inner 實作了簡單的 rpc 功能。

通過 wait_frame_inner 得到的幀不一定是 amqp_send_method 方法希望得到的應答幀,故需要對前者的傳回内容進行相應的處理,包括對 channel 關閉、connection 關閉,以及非 method 幀的處理(放進幀連結清單)。隻有在獲得正确的應答幀後才傳回。

【amqp_simple_rpc_decoded】

此函數是對 amqp_simple_rpc 的封裝,僅增加了對資料的組織處理。

【amqp_login_inner】

該函數就是使用上述的函數實作了登陸流程中的各個動作:發送協定版本資訊、進行 connection 處理、進行 sasl 處理、進行 tune 處理。詳細請參考協定文檔。

【amqp_login】

除了包含 amqp_login_inner 外,額外還增加了對 channel 信令的處理。

以上就是對 amqp_socket.c 内容的全部要點總結,相信有助于你對 rabbitmq-c 的進一步研究。