【原创】rabbitmq-c源码分析之amqp_socket.c

本文深入解读了amqp_socket.c源码中的重点功能,包括域名解析、socket创建、阻塞式socket使用、消息发送、认证流程及简单RPC实现。详细介绍了每个函数的作用、关键代码点及注意事项,旨在帮助读者更好地理解并应用RabbitMQ C客户端库。

     走读 amqp_socket.c 源码,发现若干值得注意的细节:

amqp_open_socket 

在 amqp_open_socket 函数中通过 getaddrinfo 函数进行域名解析可能会产生阻塞。其中参数指定了

?
1
2
3
4
5
6
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。

?
1
sockfd = ( int )socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol);

socket 创建后仅设置了 SO_NOSIGPIPE(该标识仅在 IOS 系统下有效) 和 TCP_NODELAY 选项,之后就进行了 connect 动作,说明该 socket 为阻塞式用法,并且未绑定本地任何地址。这样的结果是 connect 会根据连接到的对端地址自动绑定本地对应地址。

另外,由于处理的是阻塞式 socket ,故 connect 仅对出错返回进行了简单处理。唯一可能需要注意的,实现中没有 connect 重连机制,直接结果是对每一个地址仅尝试 connect 一次。


【amqp_send_header】

该函数仅需看一下 send 函数的 flags 即可。

?
1
send(state->sockfd, ( void *)header, 8, MSG_NOSIGNAL);

设置 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 的进一步研究。


<think>好的,我现在需要处理用户关于rabbitmq-c库中amqp_login函数的用法的问题。用户希望了解它的使用说明、文档和示例。首先,我得回忆一下自己对RabbitMQ和这个C库的了解。 首先,rabbitmq-c是一个用于RabbitMQ交互的C语言客户端库。amqp_login函数应该是用于建立连接时的认证步骤。我需要确认这个函数的参数和返回值,以及正确的调用方法。 接下来,我需要查阅官方文档或者可靠的资料来确保信息的准确性。记得amqp_login是在建立连接时使用的,通常在创建socket并连接到RabbitMQ服务器之后调用。函数的参数可能包括连接对象、虚拟主机、凭证等。 然后,考虑用户可能需要一个示例代码。这时候需要确保示例代码正确,包含必要的步骤,比如初始化、创建连接、打开通道,以及错误处理。同时要注意资源管理,比如最后要关闭连接和释放资源。 另外,用户可能遇到常见问题,比如认证失败或连接超时,需要给出排查建议。例如检查用户名密码是否正确,虚拟主机是否存在,防火墙设置等。 最后,生成相关问题,帮助用户进一步学习。比如其他认证方式、错误处理机制,或者连接池的使用。这些问题应该当前主题相关,能够引导用户深入理解。</think>### rabbitmq-c 库中 `amqp_login` 函数使用说明 #### 1. 函数功能 `amqp_login` 是 rabbitmq-c 库中用于 RabbitMQ 服务器建立认证连接的函数,需在创建 TCP 连接后调用。它通过 AMQP 协议完成身份验证,支持用户名、密码和虚拟主机(vhost)的校验[^1]。 #### 2. 函数原型 ```c amqp_rpc_reply_t amqp_login( amqp_connection_state_t state, // 连接状态对象 char const *vhost, // 虚拟主机路径(如"/") int channel_max, // 最大通道数(通常填0,由服务器决定) int frame_max, // 最大帧大小(通常填131072) int heartbeat, // 心跳间隔(0表示禁用) amqp_sasl_method_enum sasl_method, // 认证方式(如AMQP_SASL_METHOD_PLAIN) ... ); ``` #### 3. 参数说明 | 参数 | 说明 | |------|------| | `state` | 通过 `amqp_new_connection()` 创建的连接状态对象 | | `vhost` | RabbitMQ 的虚拟主机名称,默认使用`"/"` | | `sasl_method` | 认证机制,常用 `AMQP_SASL_METHOD_PLAIN` 表示明文密码 | #### 4. 使用示例 ```c #include <amqp.h> int main() { amqp_connection_state_t conn = amqp_new_connection(); amqp_socket_t *socket = amqp_tcp_socket_new(conn); // 连接到服务器(需先建立TCP连接) if (amqp_socket_open(socket, "localhost", 5672) != AMQP_STATUS_OK) { fprintf(stderr, "连接失败\n"); return 1; } // 进行登录认证 amqp_rpc_reply_t reply = amqp_login( conn, "/", // vhost 0, // channel_max 131072, // frame_max 0, // heartbeat AMQP_SASL_METHOD_PLAIN, "guest", // 用户名 "guest" // 密码 ); if (reply.reply_type != AMQP_RESPONSE_NORMAL) { fprintf(stderr, "认证失败\n"); return 1; } // 后续操作(如打开通道、声明队列等) amqp_channel_open(conn, 1); // 关闭连接 amqp_connection_close(conn, AMQP_REPLY_SUCCESS); amqp_destroy_connection(conn); return 0; } ``` #### 5. 常见问题排查 - **认证失败**:检查用户名/密码是否匹配服务器配置 - **vhost不存在**:使用 `rabbitmqctl list_vhosts` 确认虚拟主机存在 - **连接超时**:检查防火墙是否开放 5672 端口(或 TLS 的 5671 端口)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值