1

我正在阅读有关使用 SO_LINGER 套接字选项通过将逗留时间设置为零来故意“暗杀”时间等待状态的信息。这本书的作者接着说我们永远不应该这样做,而且一般来说我们永远不应该干预时间等待状态。然后他立即建议使用 SO_REUSEADDR 选项绕过时间等待状态。

我的问题是,有什么区别?在这两种情况下,您都过早地终止了时间等待状态并冒着接收重复段的风险。为什么一个好一个坏?

4

3 回答 3

3

TIME_WAIT 是绝对正常的。它发生在本地端的 TCP FIN 后跟来自远程位置的 TCP FIN ACK 之后。在 TIME_WAIT 中,您只是在等待任何杂散数据包到达本地地址。但是,如果有一个丢失或杂散的数据包,则 TIME_WAIT 确保 TTL 或“生存时间”在再次使用该地址之前到期。

如果您使用 SO_REUSEADDR 那么您基本上是在说,我会假设没有杂散数据包。现代、可靠的 TCP 网络越来越有可能发生这种情况。虽然仍有可能,但不太可能。

将 SO_LINGER 设置为零会导致您启动异常关闭,也称为“猛烈关闭连接”。在这里,您不尊重 TIME_WAIT 并忽略流浪数据包的可能性。

如果您看到 FIN_WAIT_1,那么这可能会导致问题,因为远程位置没有发送 TCP FIN ACK 来响应您的 FIN。因此,进程要么被杀死,要么 TCP FIN ACK 由于网络分区或路由错误而丢失。

当您看到 CLOSE_WAIT 时,您遇到了问题,这里您正在泄漏连接,因为在给定 TCP FIN 时您没有发送 TCP FIN ACK。

于 2009-02-25T21:45:27.490 回答
0

我做了更多阅读,这是我对发生的事情的理解(希望是正确的):

当您在设置了 SO_REUSEADDR 的套接字上调用 close (或您的应用程序崩溃)时,会发生以下序列:

  1. TCP 发送发送缓冲区中的任何剩余数据和一个 FIN
  2. 如果 close 被调用,它会立即返回,如果任何剩余的数据已成功传递,则不会指示。
  3. 如果发送了数据,则对等方发送数据 ACK
  4. 对端发送 FIN 的 ACK 并发送自己的 FIN 包
  5. 对等方的 FIN 被确认并释放套接字资源。
  6. 套接字没有进入 TIME-WAIT。

当您关闭 SO_LINGER 时间设置为零的套接字时:

  1. TCP 丢弃发送缓冲区中的所有数据
  2. TCP 向对端发送 RST 数据包
  3. 套接字资源被释放。
  4. 套接字没有进入 TIME-WAIT

因此,除了将 linger 设置为零是一种黑客和不良风格之外,它也是一种不礼貌的做法,因为它不会完全关闭连接。

于 2009-02-28T21:26:00.447 回答
0

我已经使用 SO_REUSEADDR 到通配符 bind() 到某个其他程序已经打开连接的本地端口。事实证明,只要没有两个套接字同时尝试在同一个地址/端口组合上侦听(),这种特殊用途就不会导致问题。

于 2011-03-08T17:35:44.797 回答