SO_REUSEADDR(setsockopt 选项)的含义是什么 - Linux?[重复]
- 2024-10-09 09:10:00
- admin 原创
- 82
问题描述:
从手册页中:
SO_REUSEADDR 指定用于验证提供给 bind() 的地址的规则应允许重用本地地址(如果协议支持)。此选项采用 int 值。这是一个布尔选项
什么时候应该使用它?为什么“重用本地地址”会给出?
解决方案 1:
TCP 的主要设计目标是在出现数据包丢失、数据包重新排序以及(这里的关键)数据包重复的情况下实现可靠的数据通信。
TCP/IP 网络堆栈在连接时如何处理所有这些问题相当明显,但在连接关闭后会发生一种极端情况。如果在对话结束时发送的数据包被复制并延迟,以至于4 路关闭数据包在延迟数据包之前到达接收方,会发生什么情况?堆栈会尽职尽责地关闭其连接。然后,延迟的重复数据包出现。堆栈应该怎么做?
更重要的是,如果一个在给定 IP 地址 + TCP 端口组合上打开套接字的程序关闭了它的套接字,然后过了一会儿,又有一个程序出现并想要侦听相同的 IP 地址和 TCP 端口号,那么它该怎么办?(典型情况:程序被终止并迅速重新启动。)
有两种选择:
禁止重复使用该 IP/端口组合,时间至少为数据包传输的最大时间的 2 倍。在 TCP 中,这通常称为 2× MSL延迟。有时您还会看到 2× RTT,这大致相当。
这是所有常见 TCP/IP 堆栈的默认行为。2×MSL 通常介于 30 到 120 秒之间,并在netstat
输出中显示为TIME_WAIT
周期。在此时间之后,堆栈假定由于TTL过期,所有恶意数据包都已在途中被丢弃,因此套接字将离开该状态,从而允许重新使用该 IP/端口组合。TIME_WAIT
允许新程序重新绑定到该 IP/端口组合。在具有BSD 套接字接口的堆栈中(基本上是所有 Unix 和类 Unix 系统,以及通过Winsock的 Windows ),您必须在调用 之前通过设置
SO_REUSEADDR
选项 via来请求此行为。setsockopt()
`bind()`
SO_REUSEADDR
在网络服务器程序中设置最为常见,因为常见的使用模式是进行配置更改,然后需要重新启动该程序才能使更改生效。如果没有SO_REUSEADDR
,bind()
如果在终止前一个实例时有与前一个实例的连接打开,则重新启动的程序的新实例中的调用将失败。这些连接将使 TCP 端口保持该状态TIME_WAIT
30-120 秒,因此您属于上述情况 1。
设置的风险SO_REUSEADDR
在于它会造成歧义:TCP 数据包头中的元数据不够唯一,以至于堆栈无法可靠地判断数据包是否陈旧,因此应该将其丢弃,而不是传送到新侦听器的套接字,因为它显然是为现在已经死亡的侦听器设计的。
如果您不认为这是真的,那么所有监听机器的 TCP/IP 堆栈必须与每个连接一起做出该决定:
本地 IP:不是每个连接都唯一的。事实上,我们这里的问题定义表明我们有意重复使用本地 IP。
本地 TCP 端口:同上。
远程 IP:造成歧义的机器可以重新连接,因此这无助于消除数据包的正确目的地歧义。
远程端口:在运行良好的网络堆栈中,传出连接的远程端口不会很快被重用,但它只有 16 位,因此您有 30-120 秒的时间来强制堆栈处理几万个选择并重用该端口。早在 20 世纪 60 年代,计算机就可以如此快速地完成工作。
如果您的答案是远程堆栈应该TIME_WAIT
在其端执行类似操作以禁止临时 TCP 端口重用,则该解决方案假定远程主机是良性的。恶意行为者可以自由重用该远程端口。
我认为侦听器的堆栈可以选择严格禁止仅来自 TCP 4 元组的连接,以便在该TIME_WAIT
状态下,给定的远程主机无法重新连接到同一个远程临时端口,但我不知道有任何 TCP 堆栈具有这种特殊的改进。
本地和远程 TCP 序列号:这些序列号也不够唯一,以至于新的远程程序无法得出相同的值。
如果我们今天重新设计 TCP,我认为我们会将TLS或类似的东西集成为非可选功能,这样做的一个效果是使这种无意和恶意的连接劫持变得不可能。这需要添加大字段(128 位及以上),这在 1981 年发布当前版本的 TCP ( RFC 793 ) 文档时根本不切实际。
如果没有这样的强化,允许重新绑定所造成的歧义TIME_WAIT
意味着您可能会出现以下情况:a) 将原本要发送给旧侦听器的陈旧数据错误地传送到属于新侦听器的套接字,从而破坏侦听器的协议或将陈旧数据错误地注入连接;或 b) 将新侦听器套接字的新数据错误地分配给旧侦听器的套接字,从而无意中丢弃。
安全的做法是等待这段TIME_WAIT
时间过去。
最终,这取决于成本的选择:等待TIME_WAIT
一段时间或承担不必要的数据丢失或无意中数据注入的风险。
许多服务器程序都冒这个风险,认为最好立即恢复服务器,以免错过任何不必要的传入连接。
这不是普遍的选择。许多程序(甚至是需要重新启动才能应用设置更改的服务器程序)都选择不做SO_REUSEADDR
任何更改。程序员可能知道这些风险并选择不做任何更改,或者他们可能不知道这些问题,但从明智的默认设置中获益。
一些网络程序为用户提供了配置选项的选择,将责任推卸给最终用户或系统管理员。
解决方案 2:
SO_REUSEADDR 允许您的服务器绑定到处于 TIME_WAIT 状态的地址
。
此套接字选项告诉内核,即使此端口繁忙(处于 TIME_WAIT 状态),也请继续重用它。如果它繁忙,但处于其他状态,您仍会收到地址已在使用中的错误。如果您的服务器已关闭,然后在其端口上的套接字仍处于活动状态时立即重新启动,则此功能很有用。
来自unixguide.net
解决方案 3:
当您创建套接字时,您实际上并不拥有它。操作系统(TCP 堆栈)为您创建它并为您提供一个句柄(文件描述符)以访问它。当您的套接字关闭时,操作系统需要时间“完全关闭它”,同时它会经历几个状态。正如 EJP 在评论中提到的,最长的延迟通常来自 TIME_WAIT 状态。需要此额外延迟来处理终止序列末尾的边缘情况,并确保最后的终止确认通过或由于超时而使另一端重置。您可以在此处找到有关此状态的一些额外注意事项。主要注意事项如下:
请记住,如果可能的话,TCP 会保证所有传输的数据都将被送达。当您关闭套接字时,服务器将进入 TIME_WAIT 状态,以确保所有数据都已发送。当套接字关闭时,双方通过向对方发送消息来同意不再发送数据。在我看来,这已经足够好了,握手完成后,套接字应该关闭。问题有两个方面。首先,无法确保最后一个确认已成功传达。其次,网络上可能存在“游离重复”,如果要送达,必须处理这些重复。
如果您尝试快速创建具有相同 ip:port 对的多个套接字,则会收到“地址已在使用中”错误,因为较早的套接字尚未完全释放。使用 SO_REUSEADDR 将消除此错误,因为它将覆盖对任何先前实例的检查。
- 2024年20款好用的项目管理软件推荐,项目管理提效的20个工具和技巧
- 2024年开源项目管理软件有哪些?推荐5款好用的项目管理工具
- 项目管理软件有哪些?推荐7款超好用的项目管理工具
- 项目管理软件哪个最好用?盘点推荐5款好用的项目管理工具
- 项目管理软件有哪些最好用?推荐6款好用的项目管理工具
- 项目管理软件有哪些,盘点推荐国内外超好用的7款项目管理工具
- 2024项目管理软件排行榜(10类常用的项目管理工具全推荐)
- 项目管理软件排行榜:2024年项目经理必备5款开源项目管理软件汇总
- 2024年常用的项目管理软件有哪些?推荐这10款国内外好用的项目管理工具
- 项目管理必备:盘点2024年13款好用的项目管理软件