最近在一个碰到一个socket相干的异样。

  • 环境:linux
  • 我的项目:C++,波及大量网络IO
  • 察看对象:一个常驻过程,既是客户端,也是服务端
  • 景象:特定操作后,隔132分钟后,过程便会主动退出。能通过exception异样类捕捉到errno为110, 对应的message为"Connection timed out"。

剖析过程:

假如1:从该Connection time out这音讯提醒,联合该我的项目波及大量的socket通信,很天然地联想到是该过程在调用connect(),与服务端建设连贯的时候出了问题?

颠覆假如1:connect()是linux的C实现的库函数,不会抛异样(异样是C++中的机制)。

假如2:回到一开始,正是因为代码里有异样捕捉,才得悉errno,的确抛了异样。那么就有可能是人为地依据errno,被动throw进去的。

搜寻得悉,我的项目中有大量的throw system_error(errno, system_category()),合乎假如2。

在这种有大量可疑点的状况下,被动从代码的角度去一个个刻意点排查是很吃力的。既然定时可能复现,且有抛异样的机制。那来一个刻舟求剑,不捕获异样解决,让程序间接core dump,便可依据core文件的堆栈信息,定位到起因。

最初无效地找到问题所在:程序作为服务端,其客户端在运行过程中退出了,服务端的连贯没有进行敞开,代码层面没有close与客户端的连贯socket,且该连贯的socket设置了SO_KEEPALIVE属性。这就呈现了,默认7200s,服务端就会往一个半关上的连贯发送一个心跳报文,对方是不会回复该报文的,引发连贯超时的谬误。

解决方案:服务端在检测到客户端发动敞开连贯后,及时进行敞开连贯。
惯例来说,客户端close --> 服务端接管完接收缓冲区的数据,close --> 连贯敞开。