共计 773 个字符,预计需要花费 2 分钟才能阅读完成。
最近在一个碰到一个 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 –> 连贯敞开。
正文完