避免 TIME_WAIT
Posted
技术标签:
【中文标题】避免 TIME_WAIT【英文标题】:Avoiding TIME_WAIT 【发布时间】:2009-12-18 22:27:36 【问题描述】:我试图在客户端中。我连接然后设置 O_NONBLOCK 和 SO_REUSEADDR。我调用 read 直到它返回 0。当 read 返回 0 时,errno 也为 0。我将此解释为服务器关闭连接的标志。但是,如果我调用 close,则套接字将设置为 TIME_WAIT,正如 netstat 所确认的那样。
由于我与同一个主机/端口建立了多个连接,我最终开始看到“正在使用的地址”错误(请参阅http://hea-www.harvard.edu/~fine/Tech/addrinuse.html)。
我应该在 read 返回 0 后调用 close 吗?如果我不这样做,文件描述符会被释放吗?
【问题讨论】:
旁注:读取返回 0 时 errno 值未定义 - errno 仅在失败后定义。 【参考方案1】:启动关闭连接的一侧是最终处于TIME_WAIT
状态的一侧。 read()
返回 0 应该表示服务器首先关闭了套接字,所以是的 - 这应该意味着 TIME_WAIT
最终在服务器端,客户端通过 LAST_ACK
。
归根结底,您无法避免TIME_WAIT
状态。即使您成功地将其从客户端移动到服务器端,您仍然无法重新使用该 (server host, server port, client host, client port)
元组,直到 TIME_WAIT
结束(无论它在哪一侧)。
由于该元组的三个部分在您的场景中是固定的(server host
、server port
、client host
),因此您实际上只有以下选项:
尝试使更多客户端端口可用。默认情况下,某些操作系统仅将一小部分可用端口用于“临时端口”(在这方面我不确定 OSX)。如果是这种情况,请查看是否可以通过操作系统中的配置调整来更改范围,或者让应用程序使用bind()
/connect()
在循环中寻找工作端口,直到连接正常。
通过在客户端上使用多个 IP 地址来扩展可用的 client host
值的数量。不过,您必须将应用程序 bind()
专门用于这些 IP 地址之一。
通过在服务器上使用多个端口和/或 IP 地址来扩展可用的 server host
/server port
值的数量。客户端需要选择一个连接(循环、随机等)。
如果可行,这可能是最好的选择:重构您的协议,以便完成的连接不会关闭,而是进入“空闲”状态,以便以后可以重新使用,而不是打开一个新的连接(如 HTTP 保持活动)。
【讨论】:
抱歉对一个老问题发表评论,但这个答案的第一段不应该是“发起关闭连接的一方是最终处于 TIME_WAIT 状态的一方”?我似乎记得在某本书中读过,而且,这似乎暗示了hea-www.harvard.edu/~fine/Tech/addrinuse.html【参考方案2】:稍后在同一页面上,他们提到了 SO_REUSEADDR。这就是你需要的。 您肯定希望在读取文件描述符返回零时关闭它。
【讨论】:
对不起。我忘了补充说我确实设置了 SO_REUSEADDR。在文章中看到,当您连接到同一端口/主机时,它不会阻止使用中的地址错误。【参考方案3】:在客户端设置 SO_REUSEADDR 对服务器端没有帮助,除非它也设置了 SO_REUSEADDR
【讨论】:
以上是关于避免 TIME_WAIT的主要内容,如果未能解决你的问题,请参考以下文章