libevent中关于bufferevent_socket_connect的使用小结

本文探讨了bufferevent_socket_connect的连接行为,包括连接失败原因、网络延迟后的重连策略、多线程使用注意事项,并提到了网络异常时的错误处理和超时判断。还分享了libevent多线程支持的配置技巧和一个意外的回调问题观察。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

经过多次代码测试,总结如下:

  1. bufferevent_socket_connect 返回0,不代表和服务器连接成功,返回-1一定是连接失败(简单看了下源码,的确大部分情况都是返回0,包括连接被拒绝等)
  2. 网线未插(wifi未连接),服务器没开,bufferevent_socket_connect立即返回0,但在后台继续请求连接(前提socket已被设置成非阻塞),若无进一步操作,将在130秒后,报错:110-Connection timed out
  3. 在上述状态下,若先插网线,再开服务器,几秒之后,可以成功建立连接,也有可能报错:113-No route to host
  4. 在上述状态下,若先开服务器,再插网线,十几秒之后,报错:113-No route to host
  5. 网络连接已正常,服务器没开,立即报错:111-Connection refused
  6. 网络连接正常状态下,若服务器关闭,则BEV_EVENT_EOF事件触发,客户端可通过该事件确认服务器被关闭
  7. 上述所有错误都会产生BEV_EVENT_ERROR事件,且触发event_cb回调,客户端可在event_cb回调函数中处理这些错误信息,包括网络重连,或向HMI显示网络问题,或将这些信息输出到系统日志
  8. bufferevent_free会关闭套接字(BEV_OPT_CLOSE_ON_FREE开启情况下),如果该套接字正在进行connect,则会立即结束。不过,测试发现不会立即释放该sockfd,比如刚关闭的套接字sockfd=9,free掉之后,该sockfd关闭,但此时若新建sockfd,则sockfd=10,而不是9.
  9. 通过socket()connect() 创建套接字以及建立连接时,默认是阻塞的,一种处理方法是通过定时器终止connect以避免阻塞,不过该方法对bufferevent_socket_connect无效(当传入的sockfd是阻塞的时候),SIGALAM触发了之后,仍继续connect,netstat查看,的确还在SYN_SENT状态。故需要使用上述第8点方法,若超时未连接上,又无错误返回,直接bufferevent_free,然后重连
  10. event_base_new在主线程创建basebufferevent_socket_new在子线程创建bufferevent监听网口(以及event_new也在子线程创建event事件进行串口、CAN口监听),此时需开启libevent的多线程支持功能,否则无法将event或bufferevent添加到base。Linux下开启多线程支持需以下三句代码:
evthread_use_pthreads();
base = event_base_new();
evthread_make_base_notifiable(base);

2021-5-16 更新

前几天调试外设时,在一个非正常的,实际不会发生的工况下模拟测试时,发现一个怪异的问题:

event_base_new在主线程创建,另起一个线程进行bufferevent_socket_newbufferevent_socket_connect,然后等待回调bev_event_cb执行,检查是否连接成功,此时,如果主线程休眠了,bev_event_cb貌似不会立即回调,而是等到主线程休眠结束后才回调……

由于时间紧迫,而且libevent这块儿框架基本都写好了,就懒得继续深入测试分析了,先记下来再说,以后有空再研究吧。

2021-8-2 更新
当bufferevent连接成功后,客户端正常发送数据,服务器正常接收,在未开启接收超时的情况下。此时,如果将网线拔出来,客户端和服务器都不会报错(event_cb不会被回调,因此在event_cb中写的网络重连逻辑也不会被触发)。bufferevent_write仍然返回0,也即写入成功(写入发送缓冲区)。

一段时间后,重新插上网线。此时,服务器将接收到一堆数据,该数据为网线拔出来之后,客户端写入发送缓冲区但没有被服务器接收的数据。接收完毕之后,恢复正常通讯在这里插入图片描述
上图中,客户端每秒发送一串字符串“Hello,this is a test for bufferevent_write function!”,中途将网线拔出,一段时间后再插上,接收到一堆字符串后,再次恢复到正常通讯状态。

因此,目前通过设置接收超时(bufferevent_set_timeouts)来判断网络连接是否正常,若在设定的时间内没有收到服务器发送的数据,则认为网络断开,关闭bufferevent后重连。

评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值