搞不懂einprogress状态咋回事?简单几步教你查询理解

吉云

最近在搞点网络编程的小玩意儿,具体来说就是写个客户端去连服务器,碰到了个挺有意思的情况,代码跑起来有时候就连不上,返回个错误,但有时候又莫名其妙好了。这给我整得有点懵。

遇到问题

就是那个connect函数,按理说成功返回0,失败返回-1。我这边,经常拿到-1,第一反应就是,完了,连接失败。要么是服务器没开,要么是网络不通,要么就是我地址端口写错了。

搞不懂einprogress状态咋回事?简单几步教你查询理解

但我查来查去,服务器好好的,网络也没问题,地址端口更是核对了好几遍,没毛病。这就奇怪了。

排查过程

没办法,只能看看到底是啥错误。我就去检查那个errno,就是那个全局变量,专门存错误码的。一看,错误码是115,或者说,错误名是EINPROGRESS

EINPROGRESS?这是啥意思?“正在进行中”?连接操作还在进行中,没立刻完成?我当时就纳闷了,连接要么成功要么失败,咋还有个中间状态?

我又去翻了翻资料,结合我代码的写法,发现问题出在哪了。我用的是非阻塞的socket。对于非阻塞的socket来说,调用connect时,它不会傻等连接建立成功,而是马上返回。如果连接不能立刻建立(这很常见,网络传输需要时间嘛),它就会返回-1,同时把errno设置成EINPROGRESS,告诉你:“哥们儿,我正在努力连接,还没搞定,你等会儿再来看看情况。”

更有意思的是,我去看服务器那边的日志,发现有时候我客户端报这个错的时候,服务器那边居然显示连接已经建立成功了(就是那个ESTABLISHED状态)。这说明连接过程确实已经启动,只是客户端这边还没得到最终确认。

搞不懂einprogress状态咋回事?简单几步教你查询理解

怎么解决的

搞明白了原因,解决起来就好办了。既然它告诉我“正在进行中”,那我不能把它当成失败处理。

我试了几种法子:

  • 简单粗暴重试? 有时候再调一次connect好像能行,但感觉不靠谱,而且第二次可能还是EINPROGRESS,或者遇到其他问题。
  • 改成阻塞模式? 这倒是能解决EINPROGRESS问题,connect会一直等到连接成功或失败才返回。但我的程序设计就是需要非阻塞,不能因为这个就改回去,不然整个程序逻辑都得变。
  • 搞不懂einprogress状态咋回事?简单几步教你查询理解

  • 正确处理非阻塞逻辑: 这才是正道。既然connect发起了连接,返回了EINPROGRESS,那我接下来就得用别的方法来检查这个连接是不是真的完成了。

我的做法是,用了select(或者poll/epoll也行,看你用哪个方便)来监听这个socket描述符。当select告诉我这个socket变得“可写”的时候,就表示连接建立成功了。还得再用getsockopt检查一下socket上有没有错误(比如SO_ERROR选项),确保万无一失。如果select超时了还没可写,或者getsockopt检查到了错误,那才是真的连接失败。

总结

这个EINPROGRESS不是啥洪水猛兽,它就是非阻塞socket在connect时的一个正常状态反馈。告诉你后台正在忙活,需要你后续再确认一下结果。

这回折腾让我明白了,用非阻塞模式就得有处理这种“中间状态”的准备。不能简单地把返回-1都当成连接失败。得看errno,如果是EINPROGRESS,就得有耐心,用select之类的机制去等最终结果。

这下心里踏实了,程序跑起来也稳定多了。记录一下,免得下次再踩坑。

免责声明:由于无法甄别是否为投稿用户创作以及文章的准确性,本站尊重并保护知识产权,根据《信息网络传播权保护条例》,如我们转载的作品侵犯了您的权利,请您通知我们,请将本侵权页面网址发送邮件到qingge@88.com,深感抱歉,我们会做删除处理。

目录[+]