SO_REUSEADDR(setsockopt选项)是什么意思 – Linux?
从手册页:
SO_REUSEADDR指定用于validation提供给bind()的地址的规则应允许重用本地地址(如果协议支持)。 该选项采用一个int值。 这是一个布尔选项
我应该什么时候使用它? 为什么“重用本地地址”给予?
TCP的主要devise目标是在数据包丢失,数据包重新sorting以及密钥(这里是数据包重复)的情况下允许可靠的数据通信。
TCP / IPnetworking堆栈在连接完成时处理所有这些事情是相当明显的,但是在连接closures之后会出现一个边缘情况。 如果在通话结束时正确发送的数据包被复制和延迟,会发生什么情况,使得4路closures数据包在延迟数据包之前到达接收机? 堆栈忠诚地closures了它的连接。 然后,延迟的重复数据包显示出来。 堆栈应该做什么?
更重要的是,如果拥有该连接的程序立即死亡,那么应该怎么办?然后另一个启动想要相同的IP地址和TCP端口号?
有几个select:
-
不允许重复使用该IP /端口组合至less2倍数据包可能在飞行中的最大时间。 在TCP中,这通常被称为2× MSL延迟。 你有时也会看到2× RTT ,这大致相当。
这是所有常见TCP / IP堆栈的默认行为。 2×MSL通常在30到120秒之间。 (这是
TIME_WAIT
时间段。)在此之后,堆栈认为任何stream氓数据包由于过期的TTL而在路由中被丢弃,因此它离开TIME_WAIT
状态,允许重新使用该IP /端口组合。 -
允许新程序重新绑定到该IP /端口组合。 在使用BSD套接字接口的堆栈中(基本上所有的Unix和类Unix系统,再加上Winsock的 Windows
setsockopt()
在调用bind()
之前,必须通过setsockopt()
来设置SO_REUSEADDR
选项。
SO_REUSEADDR
通常在服务器程序中设置。
原因是,一个常见的模式是您更改服务器configuration文件,并需要重新启动该服务器以使其重新加载其configuration。 如果在没有SO_REUSEADDR
,重新启动的程序的新实例中的bind()
调用将会失败。 这些连接将TCP端口保持在TIME_WAIT
状态30-120秒,因此您将陷入上面的情况1。
安全的做法是等待TIME_WAIT
期,但实际上这不是一个足够大的风险,值得这样做。 最好让服务器立即备份,以便不会错过任何更多的连接。
SO_REUSEADDR允许你的服务器绑定到一个地址
TIME_WAIT状态。
这个套接字选项告诉内核,即使这个端口很忙(处于TIME_WAIT状态),仍然继续并重新使用它。 如果它很忙,但与另一个国家,你仍然会得到一个已经使用错误的地址。 如果您的服务器已closures,然后在端口上的套接字仍处于活动状态时立即重新启动,这将非常有用。
从unixguide.net
当你创build一个套接字时,你并不是真的拥有它。 操作系统(TCP堆栈)为你创build它并给你一个句柄(文件描述符)来访问它。 当您的套接字closures时,操作系统需要一段时间才能“完全closures”,同时它会经历几种状态。 正如EJP在评论中提到的,最长的延迟通常是从TIME_WAIT状态。 这个额外的延迟需要在终止序列的最后处理边缘情况,并确保最后的终止确认通过或者由于超时而使对方重置。 在这里你可以find关于这个状态的一些额外考虑。 主要考虑如下:
请记住,TCP保证所有传输的数据将被传送,如果可能的话。 closures套接字时,服务器进入TIME_WAIT状态,只是为了确保所有数据都已经过。 当一个套接字closures时,双方同意通过发送消息给对方,他们将不再发送数据。 这对我来说似乎足够好了,握手完成后,sockets应该closures。 问题是双重的。 首先,没有办法确定最后一次通信是否成功。 其次,networking上可能存在“stream浪复制品”,如果交付的话,必须予以处理。
如果您尝试使用相同的IP:端口对创build多个套接字非常快速,则会出现“地址已被使用”错误,因为较早的套接字不会完全释放。 使用SO_REUSEADDR将摆脱这个错误,因为它将覆盖任何以前的实例的检查。