TCPsocket如何判断连接断开
socket通信报文格式SO_KEEPALIVE是系统底层的机制,⽤于系统维护每⼀个tcp连接的。
⼼跳线程属于应⽤层,主要⽤于终端和服务器连接的检查。
即使SO_KEEPALIVE检测到连接正常,但并不能保证终端和服务器连接的正常。有⼀种情况,服务器进程死了,但它和客户端的tcp连接还连着(该连接由系统维护的)。
这就是SO_KEEPALIVE不能取代⼼跳线程的原因吧。
>>>>>>#
最近在做⼀个TCP采集程序,使⽤到C/S的结构。功能⽐较的简单,就是TCP采集程序作为服务器,信令采集设备作为客户端,客户端与服务器端之间建⽴长连接之后,开始发送信令报⽂给服务器。在服务器端使⽤多线程⽅式来处理每个客户端的socket连接,服务器端不主动断开链路,也没有⼼跳机制来维护连接的状态,客户端发送数据的时间也是不⼀定的,只要有采集到信令数据时才进⾏发送。在客户端socket断开后,服务器端应该能够知道并且释放socket资源。
判断socket是否已经断开的⽅法是使⽤⾮阻塞的select⽅式进⾏socket检查,步骤如下:
1)设置接收到的socket为异步⽅式;
2)使⽤select()函数测试⼀个socket是否可读;
3)如果select()函数返回的值为1,但是使⽤recv()函数读取的数据长度为0,那么说明该socket已经断开。
4)如果recv()返回值⼩于等于0时,客户端的连接已经断开,但是还需要判断errno是否等于EINTR。如果errno=EINTR则说明recv()函数是由于程序接收到中断信号后返回的,socket连接应该还是正常,步应该close掉socket连接。
注:对于阻塞socket的recv函数会在以下三种情况下返回值:
1)接收到数据时会返回;
2)程序接收到信号时返回-1,errno=EINTR;
3)Socket出现问题时,返回-1,具体的错误码请查看man recv;
4)⼀定要养成查看man说明,内容很详细,很有帮助。
这种⽅法经过长时间的测试证明是有效的,仅供⼤家参考。
此外,UNP卷⼀上有很多socket异常情况下的模拟解释,⼤家可以去阅读下。如果⽹络中间有多级路由,路由当掉等很多情况出现,所以建议程序中在应⽤层中加⼊⼼跳(heartbeat机制)和重连来维持连接的状态。
TCP protocol has a timer to determine if the connection is abnormally closed. But this timeout value is very long by default and if you want to check this situation as soon as possible to improve performance, the best solution is to introduce a keepalive mechanism in application protocol design.
TCP协议有⼀个定时器来决定连接是否被异常关闭。但是该超时时间值缺省的情况下会⾮常长,如果你希望尽快的检查出这种状态改进性能,最好的⽅法就是在应⽤程序协议设计的时候引⼊keepalive(保持连接)机制。
>>>>>>>>
最近在做⼀个服务器端程序,C/S结构。功能⽅⾯⽐较简单就是client端与server端建⽴连接,然后发送消息给server。我在server端会使⽤专门的线程处理⼀条socket连接。这就涉及到⼀个问题,如果socket连接断开(异常,正常)后,我如何才能感知到?server端这边是绝对被动的,sever端不能主动断开连
接。也没有连接链路维持包之类的。client端发送数据的时间也是不定的。在socket连接断开后,server 要能够感知到并释放资源。
这个问题在思考测试,询问同事之后,到了⼀个⽅法,可以做到这⼀点。
当使⽤ select()函数测试⼀个socket是否可读时,如果select()函数返回值为1,且使⽤recv()函数读取的数据长度为0 时,就说明该socket 已经断开。
为了更好的判定socket是否断开,我判断当recv()返回值⼩于等于0时,socket连接断开。但是还需要判断 errno是否等于 EINTR 。如果errno == EINTR 则说明recv函数是由于程序接收到信号后返回的,socket连接还是正常的,不应close掉socket连接。
PS:对于堵塞socket的recv函数会在以下三种情况下返回:
(1)recv到数据时,会返回。
(2)在整个程序接收到信号时,返回-1。errno = EINTR。//在程序的起始阶段,屏蔽掉信号的除外。部分信号还是屏蔽不掉的。(3)socket出现问题时,返回-1.具体错误码看 man recv()
(4)⼀定要看 man 说明,很详细,很有帮助。
这种⽅法经过长时间测试后,是有效的。所以写出来让⼤家参考⼀下,请⼤家发表意见。

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。

发表评论