走读 amqp_socket.c 源码,发现若干值得注意的细节:
【amqp_open_socket 】
在 amqp_open_socket 函数中通过 getaddrinfo 函数进行域名解析可能会产生阻塞。其中参数指定了
1 2 3 4 5 6 |
|
故其会对IPv4和IPv6地址均进行查询。
创建 socket 时的代码表明,其根据实际情况(IPv4或IPv6)创建对应的socket。
1 |
|
socket 创建后仅设置了 SO_NOSIGPIPE(该标识仅在 IOS 系统下有效) 和 TCP_NODELAY 选项,之后就进行了 connect 动作,说明该 socket 为阻塞式用法,并且未绑定本地任何地址。这样的结果是 connect 会根据连接到的对端地址自动绑定本地对应地址。
另外,由于处理的是阻塞式 socket ,故 connect 仅对出错返回进行了简单处理。唯一可能需要注意的,实现中没有 connect 重连机制,直接结果是对每一个地址仅尝试 connect 一次。
【amqp_send_header】
该函数仅需看一下 send 函数的 flags 即可。
1 |
|
设置 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 的进一步研究。