SO_REUSEADDR(setsockopt选项)是什么意思 - Linux?

Ray*_*ton 57 sockets linux port ip-address setsockopt

从手册页:

SO_REUSEADDR指定在验证提供给bind()的地址时使用的规则应该允许重用本地地址(如果协议支持的话).此选项采用int值.这是一个布尔选项

我应该什么时候使用它?为什么"重用本地地址"给出了?

War*_*ung 129

TCP的主要设计目标是在数据包丢失,数据包重新排序和 - 密钥,这里 - 数据包复制时允许可靠的数据通信.

很明显TCP/IP网络堆栈如何在连接启动时处理所有这些,但是在连接关闭之后会出现边缘情况.如果在会话结束时发送的数据包被复制并延迟,以便4路关闭数据包在延迟数据包之前到达接收器会发生什么?堆栈尽职地关闭其连接.然后,延迟的重复数据包显示出来.堆栈应该做什么?

更重要的是,如果拥有该连接的程序立即死亡,那么它应该怎么办?那么另一个启动需要相同的IP地址和TCP端口号?

有几个选择:

  1. 禁止重用该IP /端口组合至少是数据包在飞行中的最大时间的2倍.在TCP中,这通常称为2× MSL延迟.您有时也会看到2× RTT,这大致相当.

    这是所有常见TCP/IP堆栈的默认行为.2×MSL通常在30到120秒之间.(这是netstat时间段.)在此之后,堆栈假定任何恶意数据包由于过期的TTL而在途中被丢弃,因此它离开状态,允许重用该IP /端口组合.TIME_WAIT

  2. 允许新程序重新绑定到该IP /端口组合.在具有BSD套接字接口的堆栈中- 基本上所有Unix和类Unix系统,以及通过Winsock的 Windows - 您必须TIME_WAIT通过SO_REUSEADDR在调用之前设置选项来询问此行为setsockopt().

bind() 最常见的是在服务器程序中设置.

原因是,一个常见的模式是您更改服务器配置文件并需要重新启动该服务器以使其重新加载其配置.如果没有SO_REUSEADDR,SO_REUSEADDR重新启动的程序的新实例中的调用将失败,如果在您杀死它时有连接打开到上一个实例.这些连接将使TCP端口保持bind()状态30-120秒,因此您将进入上面的案例1.

安全的事情是等待TIME_WAIT这段时间,但实际上这不是一个足够大的风险,值得这样做.最好立即备份服务器,以免错过任何超过必要的传入连接.

  • 很棒,非常有帮助的答案.顺便说一句:请注意以下引用[man 7 ip](http://linux.die.net/man/7/ip):*已关闭的TCP本地套接字地址在关闭后的一段时间内不可用,除非已设置`SO_REUSEADDR`标志.**使用此标志时应小心,因为它会降低TCP的可靠性.如果没有上述说明,***不是很有帮助. (7认同)
  • **重要更正**:Windows/WinSock 上的 *SO_REUSEADDR* 并没有像大多数人想象的那样 - 实际上它做了一些非常可怕的事情。引用[MSDN](https://learn.microsoft.com/de-de/windows/win32/winsock/using-so-reuseaddr-and-so-exclusiveaddruse#using-so_reuseaddr):* SO_REUSEADDR套接字选项允许套接字强制绑定到另一个套接字正在使用的端口。[...]* (7认同)
  • 要在 Windows 上获得 Unix *SO_REUSEADDR* 行为,请在套接字上调用 `setsockopt(sock, SOL_SOCKET, SO_DONTLINGER, &"\x00\x00\x00\x00", 4);`。 (2认同)
  • 对于 **UDP** 套接字,*SO_REUSEADDR* 用于代替多播。基本上,多个套接字可以绑定到同一个端口,并且它们都接收传入的数据报。 (2认同)

Wil*_*and 27

SO_REUSEADDR允许您的服务器绑定到处于
TIME_WAIT状态的地址.

此套接字选项告诉内核即使此端口忙(处于TIME_WAIT状态),也要继续并重新使用它.如果它很忙,但是有另一个状态,你仍然会得到一个已经处于使用中的地址错误.如果您的服务器已关闭,然后在其端口上的套接字仍处于活动状态时立即重新启动,则此功能非常有用.

来自unixguide.net

  • 假设您打开TCP连接.传输数据后,关闭套接字.但实际上,它将被设置为TIME_WAIT状态(TIME_WAIT =="有可能某些数据还没有交付,或者某些东西,所以我们等待一个谨慎的TCP实现:)")一段时间.除了使用REUSEADDR之外,您无法打开到同一IP /端口的另一个连接. (5认同)

Eri*_*ric 8

创建套接字时,您并不真正拥有它.操作系统(TCP堆栈)为您创建它,并为您提供一个句柄(文件描述符)来访问它.当您的套接字关闭时,操作系统在经历多个状态时需要一段时间"完全关闭它".正如EJP在评论中提到的,最长的延迟通常来自TIME_WAIT状态.在终止序列的最后处理边缘情况需要这个额外的延迟,并确保最后一个终止确认通过或由于超时而使另一侧自身重置.在这里您可以找到有关此状态的一些额外注意事项 主要考虑因素如下:

请记住,TCP保证所有传输的数据都将被传送,如果可能的话.当你关闭套接字时,服务器进入TIME_WAIT状态,只是为了真正确定所有数据都已通过.当套接字关闭时,双方同意通过向对方发送消息,他们将不再发送数据.这在我看来已经足够好了,握手完成后,插座应该关闭.问题是双重的.首先,无法确定最后一个ack是否成功通信.其次,网上可能存在"流浪复制品",如果交付则必须处理.

如果您尝试使用相同的ip:port对创建多个套接字非常快,则会得到"已在使用的地址"错误,因为早期的套接字不会完全释放.使用SO_REUSEADDR将消除此错误,因为它将覆盖任何先前实例的检查.

  • IT部门没有花时间让操作系统"注意到"它.有一个*定义的TCP状态*称为TIME_WAIT,其中TCP协议*的规范要求*操作系统在最终释放端口之前维护端口.此状态后关闭相关套接字的日期. (2认同)