为什么在套接字关闭后端口不会立即释放?

10

我发现操作系统默认情况下在服务器关闭后不会立即释放使用的端口。通过在设置套接字时添加SO_REUSEADDR可以避免这个问题,但我不明白为什么需要暂时保留端口。如果服务器关闭了,套接字也关闭了,那么传输到该端口的任何数据都无法被处理,对吧?


它是TCP套接字、UDP套接字还是其他什么东西? - Matt Ball
@MattBall 在我的情况下,它是一个TCP套接字,但我不确定UDP是否也这样做? - Xufeng
2
你是否了解TCP?其中状态图尤其值得关注。而UDP则基本上是无状态的。 - Some programmer dude
2个回答

10

当端口被释放时,它进入 TIME_WAIT 状态,以防止延迟到达第一个连接的重复数据包被传递到第二个连接。

以下情况是没有使用 TIME_WAIT 可能会发生的:

  • 从 (地址 a, 端口 p) 到 (地址 b, 端口 q) 的连接被终止
  • 从 (地址 a, 端口 p) 到 (地址 b, 端口 q) 的第二个连接建立
  • 第一个连接的重复数据包在网络中延迟,并在其序列号在第二个连接窗口之内时到达第二个连接。

这里有一个很好的 回答解释如何处理此问题。这篇文章解释了如何缓解忙碌服务器上 TIME_WAIT 的影响


第二个链接在2018年9月已经失效。文章的PDF版本可以在https://www.strayalpha.com/pubs/infocom99.pdf找到,或者使用Internet Archive https://web.archive.org/web/20170521010646/http://www.isi.edu:80/touch/pubs/infocomm99/infocomm99-web/。 - mmm444
@mmm444 谢谢!现在已经修复了。 - Sergey Kalinichenko

2
在网络套接字中,当一个端口被释放后,其他人可以立即在同一端口上设置服务器,并且原本可能打算连接到之前服务器的任何新连接(TCP)或数据包(UDP)都可能被新服务器“劫持”。如果网络中还有旧数据包,则此类情况可能会意外发生。
话虽如此,通常建议使用SO_REUSEADDR使服务器可重启,并应使用其他方法防御端口劫持(最简单的方法是使用特权端口)。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接