S.l.e!ep.¢%

像打了激速一样,以四倍的速度运转,开心的工作
简单、开放、平等的公司文化;尊重个性、自由与个人价值;
posts - 1098, comments - 335, trackbacks - 0, articles - 1
  C++博客 :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理

[tcp] 异步connect是否成功?

Posted on 2010-11-20 23:07 S.l.e!ep.¢% 阅读(757) 评论(0)  编辑 收藏 引用 所属分类: epoll
我原先的client端代码流程如下:  

创建一个socket
设为异步socket(fcntl)
将socket加入epoll
connect到远端(此时connect调用返回非0,但errno为EINPROGRESS,表示正在建立连接中)
epoll_wait之
捕获到EPOLLOUT事件,此时便认为connect已经成功,client端开始发消息

这个过程通常能够运转,但是线上环境复杂多变,如果发生这种情况:server进程调用listen开始侦听后,被gdb或信号挂住了,此时异步connect会怎样?很遗憾,client端的epoll_wait依然返回EPOLLOUT,甚至往此socket里发消息都返回成功,只有当发的消息多得占完了server端的tcp缓冲以后(窗口收缩到很小),send调用才开始失败。这时候用 losf -i 看网络连接也很有趣,client端的机器显示连接建立了,server端的却显示没有这个连接。
仔细想想,OS这样做是正确的,毕竟connect的语义只是“连接”,当server挂住时,连接还是能成功的,但你能不能往里面发消息那就是另外一回事了。

所以对于应用来说,异步socket想要知道connect后连接是不是可以正常收发数据了,还是要靠应用层的一问一答才能知道。


====== 2010.5.14 ======

昨天同事朱照远给了一个更正确的解决方案,可参考之:
收到EPOLLOUT也不能认为是TCP层次上connect(2)已经成功,要调用getsockopt看SOL_SOCKET的SO_ERROR是否为0。若为0,才表明真正的TCP层次上connect成功。至于应用层次的server是否收/发数据,那是另一回事了。”

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理