怎样判定socket连接已经关闭

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了怎样判定socket连接已经关闭相关的知识,希望对你有一定的参考价值。

1)设置接收到的socket为异步方式;

2)使用select()函数测试一个socket是否可读;

3)如果select()函数返回的值为1,但是使用recv()函数读取的数据长度为0,那么说明该socket已经断开。

4)如果recv()返回值小于等于0时,客户端的连接已经断开,但是还需要判断errno是否等于EINTR。如果errno=EINTR则说明recv()函数是由于程序接收到中断信号后返回的,socket连接应该还是正常,步应该close掉socket连接。
参考技术A 采用CAsyncSocket::AsyncSelect(FD_CLOSE),
则在远程socket关闭的时候,会触发OnClose消息。
在OnClose里面填写
if(CAsyncSocket::m_hSocket!=INVALID_SOCKET)

CAsyncSocket::Close();

CAsyncSocket::OnClose(nErrorCode);
当远程socket关闭时,自动将自己关闭。
要判断远程是否关闭,直接判断自己的
CAsyncSocket::m_hSocket是否为INVALID_SOCKET即可。本回答被提问者采纳

Socket中的TIME_WAIT状态


从上面的示意图可以看得出来,TIME_WAIT是主动关闭连接的一方保持的状态,在客户端完成数据传输之后,它就会发起主动关闭连接close(),从而进入TIME_WAIT的状态,然后在保持这个状态2MSL(max segment lifetime)时间之后,彻底关闭回收资源。为什么要这么做?明明就已经主动关闭连接了为啥还要保持资源一段时间呢?这个是TCP/IP的设计者规定的,主要出于以下两个方面的考虑:

1)防止上一次连接中的包,迷路后重新出现,影响新连接(经过2MSL,上一次连接中所有的重复包都会消失)
2)可靠的关闭TCP连接。在主动关闭方发送的最后一个 ack(fin) ,有可能丢失,这时被动方会重新发fin, 如果这时主动方处于 CLOSED 状态 ,就会响应 rst 而不是 ack。所以主动方要处于 TIME_WAIT 状态,而不能是 CLOSED 。另外这么设计TIME_WAIT 会定时的回收资源,并不会占用很大资源的,除非短时间内接受大量请求或者受到攻击。

值得一说的是,对于基于TCP的HTTP协议,关闭TCP连接的是Server端,这样,Server端会进入TIME_WAIT状态,可 想而知,对于访问量大的Web Server,会存在大量的TIME_WAIT状态,假如server一秒钟接收1000个请求,那么就会积压240*1000=240,000个 TIME_WAIT的记录,维护这些状态给Server带来负担。当然现代操作系统都会用快速的查找算法来管理这些TIME_WAIT,所以对于新的 TCP连接请求,判断是否hit中一个TIME_WAIT不会太费时间,但是有这么多状态要维护总是不好。  


HTTP协议1.1版规定default行为是Keep-Alive,也就是会重用TCP连接传输多个 request/response,一个主要原因就是发现了这个问题。  


HTTP的交互中关闭连接的不是客户端,而是服务器,所以WEB服务器会出现大量的TIME_WAIT的情况。
解决思路是让服务器能够快速回收和重用那些TIME_WAIT的资源。


主要修改/etc/sysctl.conf的以下参数:
net.ipv4.tcp_tw_reuse和net.ipv4.tcp_tw_recycle的开启都是为了回收处于TIME_WAIT状态的资源。
net.ipv4.tcp_fin_timeout这个时间可以减少在异常情况下服务器从FIN-WAIT-2转到TIME_WAIT的时间。
net.ipv4.tcp_keepalive_*一系列参数,是用来设置服务器检测连接存活的相关配置。


以上是关于怎样判定socket连接已经关闭的主要内容,如果未能解决你的问题,请参考以下文章

怎么在服务器端关闭websocket连接

面向连接的Socket服务端关闭问题

JAVA 判断Socket 远程端是否断开连接

在 socket.io 上设置高关闭超时是不是安全?

C#socket通信时,怎样判断socket双方是不是断开连接

socket 如果不关闭会自动关闭吗?为啥要心跳连接?