走讀 amqp_socket.c 源碼,發現若干值得注意的細節: 緩存
【amqp_open_socket 】 socket
在 amqp_open_socket 函數中經過 getaddrinfo 函數進行域名解析可能會產生阻塞。其中參數指定了 函數
struct addrinfo hint; ... hint.ai_family = PF_UNSPEC; /* PF_INET or PF_INET6 */ hint.ai_socktype = SOCK_STREAM; hint.ai_protocol = IPPROTO_TCP; ...
故其會對IPv4和IPv6地址均進行查詢。 學習
建立 socket 時的代碼代表,其根據實際狀況(IPv4或IPv6)建立對應的socket。 spa
sockfd = (int)socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol);
socket 建立後僅設置了 SO_NOSIGPIPE(該標識僅在 IOS 系統下有效) 和 TCP_NODELAY 選項,以後就進行了 connect 動做,說明該 socket 爲阻塞式用法,而且未綁定本地任何地址。這樣的結果是 connect 會根據鏈接到的對端地址自動綁定本地對應地址。 code
另外,因爲處理的是阻塞式 socket ,故 connect 僅對出錯返回進行了簡單處理。惟一可能須要注意的,實現中沒有 connect 重連機制,直接結果是對每個地址僅嘗試 connect 一次。 rabbitmq
【amqp_send_header】 進程
該函數僅需看一下 send 函數的 flags 便可。 文檔
send(state->sockfd, (void *)header, 8, MSG_NOSIGNAL);
設置 send 函數第三個參數爲 MSG_NOSIGNAL ,即要求進程不把信號 SIGPIPE 發送給系統,而輸出到終端。 rpc
【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 的進一步研究。