在使用TCP连接的时候,客户端链接到服务器成功,然后正常使用closesocket断开,再次连接时失败,过一会儿再连接就可以成功,不知道为什么,google了一下,终于明白了原因。
原来在TCP连接后,主动去断开的一端会进入TIME_WAIT状态,在这个状态下,会等待2MSL的时间才会把本地申请的socket资源全部释放,否则在这段时间内是不能够再次使用之前的端口进行收发数据的。而对于某些应用来说,需要断开后立刻连接,这样就不能够成功了。这个问题无法解决,只能够去设置MSL的时间,最短可以是30s。
还有的网友回帖说,在TCP断开的时候可以采用两种断开方式,一种是优雅的断开,另一种就是强制断开。优雅的断开方式是在closesocket的时候,会发送FIN包,然后等待底层资源全部发送结束后对socket进行释放,但这个过程是异步的,所以closesocket的时候会立刻返回,释放的过程由底层自己去完成,所以同样不会立刻连接成功。而强制断开则是直接发送REST,这种方式下,服务器和客户端都会立刻断开连接,但这种方式同样会进入TIME_WAIT状态,所以一样不能解决这个问题。
查了好久也没能找到解决方法,获取这个问题只能通过调整MSL时间来规避了。
TCP连接断开的时候调用closesocket函数,已经讨论过有优雅的断开和强制断开,那么如何设置断开连接的方式呢?是通过设置socket描述符一个linger结构体属性。
linger结构体数据结构如下:
struct linger
{
int l_onoff;
int l_linger;
};
有三种组合方式:
第一种
l_onoff = 0;
l_linger忽略
这种方式下,就是在closesocket的时候立刻返回,底层会将未发送完的数据发送完成后再释放资源,也就
是优雅的退出。
第二种
l_onoff非零
l_linger = 0;
这种方式下,在调用closesocket的时候同样会立刻返回,但不会发送未发送完成的数据,而是通过一个REST包强制的关闭socket描述符,也就是强制的退出。
第三种
l_onoff非零
l_linger > 0
这种方式下,在调用closesocket的时候不会立刻返回,内核会延迟一段时间,这个时间就由l_linger得值来决定。如果超时时间到达之前,发送完未发送的数据(包括FIN包)并得到另一端的确认,closesocket会返回正确,socket描述符优雅性退出。否则,closesocket会直接返回错误值,未发送数据丢失,socket描述符被强制性退出。需要注意的时,如果socket描述符被设置为非堵塞型,则closesocket会直接返回值。
关于TCP的退出暂时了解这些,遇到问题再具体分析解决。