使用SO_REUSEADDR - 先前打开的套接字会发生什么?

27
在Unix网络编程中,我通常将SO_REUSEADDR选项设置在服务器用于监听连接的套接字上。这基本上意味着在同一台机器上可以打开另一个使用相同端口的套接字。当从崩溃中恢复并且套接字没有被正确关闭时,这非常有用- 应用程序可以重新启动,它将简单地在相同的端口上打开另一个套接字并继续监听。
我的问题是,旧套接字会发生什么?毫无疑问,所有数据/连接仍将在旧套接字上接收。操作系统是否会自动关闭它?

1
澄清一下:程序崩溃后,操作系统(例如Linux内核)将自动关闭套接字。由于协议原因(TCP),您不希望立即重新打开连接。 - unixman83
3
这是一篇关于“Time_Wait”的必读文章,它探讨了这个概念对协议和可伸缩服务器的设计影响。阅读后能够更好地理解这个话题。文章链接为:http://www.serverframework.com/asynchronousevents/2011/01/time-wait-and-its-design-implications-for-protocols-and-scalable-servers.html - user246645
2个回答

31

当使用socket的程序死亡时,该套接字被视为关闭。这一点由操作系统处理,操作系统将拒绝接受来自已关闭会话的任何进一步通信。但是,如果套接字意外关闭,则另一端的计算机可能不知道对话已经结束,并且可能仍在尝试通信。

这就是TCP规范中设计的等待时间之所在,以便可以重新使用相同的端口号。因为理论上,虽然不太可能,但仍有可能出现来自旧对话的数据包,具有适当的IP地址、端口号和序列号,从而使接收服务器错误地将其插入到错误的TCP流中。

选项SO_REUSEADDR覆盖了此行为,允许您立即重用端口。实际上,您正在表示:“我理解风险并希望继续使用该端口。”


25

是的,当旧进程结束时,操作系统会自动关闭以前的套接字。通常情况下,您无法立即在同一端口上侦听,原因是尽管套接字已关闭,但仍保持2MSL状态一段时间(通常是几分钟)。操作系统会在超时后自动使旧套接字退出此状态。


当然,套接字只是一个文件句柄,会被操作系统清理掉。谢谢! - Naren
4
准确来说,TCP 端点仍处于 2MSL 状态,但套接字已经消失。 - David Schwartz
1
等待期是出于某种原因而添加到规范中的。使用SO_REUSEADDR会导致TCP堆栈违反等待期。(您的2MSL状态) - unixman83

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