我想我了解该选项的形式含义。在我现在要处理的某些旧代码中,使用该选项。客户抱怨RST作为FIN的响应,从其侧面的连接侧面响应。

我不确定我是否可以安全地将其删除,因为我不明白何时应该使用它。

您能举个例子,说明何时需要该选项?

有帮助吗?

解决方案

设置一个的典型原因 SO_LINGER 零超时是避免坐在 TIME_WAIT 状态,绑定服务器上的所有可用资源。

当TCP连接干净地关闭时,启动关闭(“主动关闭”)的末端最终以连接坐在 TIME_WAIT 几分钟。因此,如果您的协议是一个 服务器 启动连接关闭,并涉及大量短寿命的连接,然后可能容易受到此问题的影响。

不过,这不是一个好主意 - TIME_WAIT 存在是有原因的(以确保旧连接中的流浪数据包不会干扰新连接)。如果可能的话,将您的协议重新设计为客户端启动连接的协议是一个更好的主意。

其他提示

对于我的建议,请阅读最后一部分: “何时将so_linger与超时使用0”.

在我们进行一些关于:

  • 正常的TCP终止
  • TIME_WAIT
  • FIN, ACKRST

正常的TCP终止

正常的TCP终止序列看起来像这样(简化):

我们有两个同行:A和B

  1. 一个电话 close()
    • 发送 FIN 到b
    • A进入 FIN_WAIT_1 状态
  2. B接收 FIN
    • b发送 ACK
    • B进入 CLOSE_WAIT 状态
  3. 接收 ACK
    • A进入 FIN_WAIT_2 状态
  4. b呼叫 close()
    • b发送 FIN
    • B进入 LAST_ACK 状态
  5. 接收 FIN
    • 发送 ACK 到b
    • A进入 TIME_WAIT 状态
  6. B接收 ACK
    • b去了 CLOSED 状态 - IE从插座表中删除

时间的等待

因此,启动终止的同伴 - 即调用 close() 首先 - 最终会进入 TIME_WAIT 状态。

了解为什么 TIME_WAIT 状态是我们的朋友,请阅读Stevens等人的《 Unix Network编程》第三版中的第2.7节(第43页)。

但是,这可能是很多插座的问题 TIME_WAIT 在服务器上陈述,因为它最终可以防止接受新的连接。

要解决这个问题,我已经看到许多人建议在打电话之前设置so_linger套接字选项。 close(). 。但是,这是一个不好的解决方案,因为它导致TCP连接被错误终止。

相反,设计您的应用程序协议,以便始终从客户端启动连接终止。如果客户端始终知道何时读取所有剩余数据,则可以启动终止顺序。例如,浏览器从 Content-Length HTTP标头读取所有数据并可以启动关闭时。 (我知道在http 1.1中,它将使其持续一段时间以进行重复使用,然后将其关闭。)

如果服务器需要关闭连接,请设计应用程序协议,以便服务器要求客户端致电 close().

何时将so_linger与超时使用0

同样,根据“ Unix网络编程”第三版第202-203页,设置 SO_LINGER 在拨打电话之前与超时0 close() 将导致正常终止序列 不是 启动。

相反,同行设置此选项并调用 close() 将发送 RST (连接重置)指示错误条件,这就是在另一端如何看待它的方式。您通常会看到“连接重置对等”之类的错误。

因此,在正常情况下,设置真的很糟糕 SO_LINGER 在拨打电话之前与超时0 close() - 从现在开始 堕胎关闭 - 在服务器应用程序中。

但是,某些情况无论如何都必须这样做:

  • 如果您的服务器应用程序的客户端行为不当(次数,返回无效的数据等),流产关闭是有意义的,避免被卡在 CLOSE_WAIT 或最终进入 TIME_WAIT 状态。
  • 如果您必须重新启动当前具有数千个客户端连接的服务器应用程序,则可能会考虑设置此套接字选项,以避免在 TIME_WAIT (打电话时 close() 从服务器端),因为这可能会阻止服务器重新启动后获得新客户连接的可用端口。
  • 在上述书籍的第202页上,它专门说:“在某些情况下,有某些情况使用此功能发送流产的关闭。一个示例是RS-232终端服务器,它可能永远挂在 CLOSE_WAIT 试图将数据传递到卡住的终端端口,但如果有一个 RST 丢弃待处理的数据。”

我会推荐的 我认为长篇文章对您的问题给出了很好的答案。

流连忘返时,但是超时为零,TCP堆栈不会等待在关闭连接之前发送待处理数据。由于此,数据可能会丢失,但是通过以这种方式设置持续状态,您可以接受此方法,并要求立即重置连接而不是优雅地关闭。这会导致第一个被发送而不是通常的鳍。

感谢EJP的评论,请参阅 这里 有关详细信息。

您是否可以安全地删除代码中的持续状态取决于应用程序的类型:是“客户端”(打开TCP连接并首先主动关闭它),还是是“服务器”(聆听TCP Open和在另一侧启动近距离之后关闭)?

如果您的应用程序具有“客户端”(首先关闭)的味道,并且您启动并关闭了与不同服务器的大量连接(例如,当您的应用程序是一个监视应用程序监视应用程序,以监督大量不同服务器的可达性)有一个问题,即您的所有客户端连接都陷入了time_wait状态。然后,我建议您将超时缩短到比默认值小的值,以便保持优雅地关闭,但更早地释放客户端连接资源。我不会将超时设置为0,因为0不会与FIN优雅地关闭,而是用RST堕胎。

如果您的应用程序具有“客户端”的味道,并且必须从同一家服务器中获取大量的小文件,则您不应在每个文件中启动新的TCP连接,最终在Time_wait中获得大量客户端连接,而是保持连接打开,并通过相同的连接获取所有数据。可以并且应该删除持续的选项。

如果您的应用程序是“服务器”(对Peer关闭的反应关闭),则在CLOSS()您的连接优雅地关闭并释放了资源,因为您不输入time_wait状态。不应使用持续时间。但是,如果您的SEVE应用程序具有一个监督过程,可以长时间检测无效的打开连接(定义“长”),则可以从您的身边关闭此无效连接 - 将其视为错误处理的一种错误。这是通过将Linger Timerout设置为0来完成的。Close()然后将REST发送给客户,告诉他您很生气:-)

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top