你的其中一端的连接没有被及时释放掉的原因是:你没有顺利地进行TCP连接关闭的流程。最近我就因为这个问题头疼了好久,现在终于找到真正的原因和解决办法了!关键点是: 在调用close之前先发送一次数据(例如,out.write(0);) 。接下来我用通俗的语言来阐述原因。
如果你两端的程序都是在传送完数据后直接调用Socket的close方法断开连接的话,这就会有一个调用close方法谁先谁后的问题,先调用者是主动关闭TCP连接的那一方,而后调用者就是被动关闭TCP连接的那一方。
关闭TCP连接的过程中,双方总共有3个报文需要发送,主动关闭方只需发送1个报文,就是断开请求的报文,被动关闭方要发送2个报文,分别是 回应主动关闭方发来的断开请求报文的第一次确认报文 和 第二次确认报文,第二次的确认报文用来确认已经没有数据需要发送了。
主动关闭方发送了断开请求报文后,就进入了等待被动关闭方发送确认报文的状态,一般情况下,被动关闭方马上就会发送第一次确认报文。主动关闭方收到第一次确认报文后,就会等被动关闭方的第二次确认报文,直到超时,套接字资源被操作系统回收(P.S. 虽然书上不是这么说的,但是实际的OS就是这么处理的,原因下面再说)。此时如果被动关闭方发送了第二次确认报文,整个TCP连接关闭流程就顺利结束了,所有资源就会被OS回收。
重点来了,问题在于,作为被动关闭方的程序中,在主动关闭方等待被动关闭方发送第二次确认报文时,就算执行了Socket的close也不会发送第二次确认报文,只有向主动关闭方发送数据(任意)后,被动关闭方才会发送第二次确认报文,整个流程才能顺利进行,TCP连接的资源才会被释