关于服务端的FIN_WAIT2

服务端开启了TCP服务,客户端连接,正常的情况下当服务端closesocket后向客户端发送FIN,客户端回应ACK,此时服务端进入FIN_WAIT2状态,等待客户端发送FIN然后进入CLOSED。

这时,客户端还可以send一次数据,send完后,服务端收到后就会向客户端发送RST并进入CLOSED

若客户端始终不发送数据,并且也不Close,那么服务端的FIN_WAIT2会持续要一个默认超时(一般是60s),这个种残留链接太多的时候可能会消耗服务端资源,降低性能,甚至无法正常工作。

我们可以使用SO_LINGER来改变关闭连接的行为

struct linger  lg;
lg.l_onoff = 1;
lg.l_linger = 0;
setsockopt(sk, SOL_SOCKET, SO_LINGER, (char*)&lg, sizeof(lg));      

l_onoffl_lingerclosesocket行为发送队列底层行为
l零忽略立即返回。保持直至发送完成。系统接管套接字并保证将数据发送至对端。
非零立即返回。立即放弃。直接发送RST包,自身立即复位,不用经过2MSL状态。对端收到复位错误号。
非零非零阻塞直到l_linger时间超时或数据发送完成。(套接字必须设置为阻塞zhuan)在超时时间段内保持尝试发送,若超时则立即放弃。超时则同第二种情况,若发送完成则皆大欢喜。

另外,除了SO_LINGER的方式,还有一种知其然不知其所以然的方法,这是在调试一个服务程序时发现的,没搞清楚其内部原由:

使用ReadFile对Socket发起一次读取,其中使用到OVERLAPPED数据结构,这里非常关键

OVERLAPPED ov;

ov.hEvent = 0;                //必须置零

ov.OffsetHigh=0;           //必须置零

DWORD nRead = 0;

char chBuf[100];

BOOL blRet = ReadFile(sk, chBuf, 10,(LPDWORD)(&nRead), &ov);//肯定读不到数据

closesocket(sk); //此时关闭socket,可以直接发送RST,而不经过四次握手

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值