dim*_*mba 84 sockets networking tcp setsockopt so-linger
我想我理解该选项的正式含义.在我正在处理的一些遗留代码中,使用了该选项.客户抱怨RST作为对其接近的连接的FIN的回应.
我不确定我是否可以安全地将其删除,因为我不明白何时应该使用它.
能否举例说明何时需要该选项?
mgd*_*mgd 171
对于我的建议,请阅读最后一节:"何时使用超时0的SO_LINGER".
在我们开始讨论之前:
TIME_WAITFIN,ACK和RST正常的TCP终止序列看起来像这样(简化):
我们有两个同行:A和B.
close()
FIN给BFIN_WAIT_1状态FIN
ACK给ACLOSE_WAIT州ACK
FIN_WAIT_2状态close()
FIN给ALAST_ACK州FIN
ACK给BTIME_WAIT状态ACK
CLOSED状态 - 即从套接字表中删除因此,启动终止的对等体 - 即close()首先调用- 将最终处于该TIME_WAIT状态.
要了解TIME_WAIT州为什么是我们的朋友,请阅读Stevens等人的"UNIX网络编程"第三版第2.7节(第43页).
但是,它可能是TIME_WAIT服务器上状态很多套接字的问题,因为它最终可能会阻止接受新连接.
为了解决这个问题,我看到很多人建议在调用之前将超时0设置为SO_LINGER套接字选项close().但是,这是一个糟糕的解决方案,因为它会导致TCP连接因错误而终止.
相反,请设计应用程序协议,以便始终从客户端启动连接终止.如果客户端总是知道它何时读取了所有剩余数据,则它可以启动终止序列.例如,浏览器Content-Length在读取所有数据时从HTTP标头知道并且可以启动关闭.(我知道在HTTP 1.1中它会保持打开一段时间以便重用,然后关闭它.)
如果服务器需要关闭连接,请设计应用程序协议,以便服务器要求客户端进行呼叫close().
同样,根据"UNIX网络编程"第三版第202-203页,SO_LINGER在调用之前使用超时0进行设置close()将导致不启动正常终止序列.
相反,设置此选项和调用的对等体close()将发送RST(连接重置),指示错误条件,这是在另一端感知它的方式.您通常会看到"按对等方重置连接"等错误.
因此,在正常情况下,在服务器应用程序中SO_LINGER调用之前设置超时0 close()(从现在开始称为abortive close)是一个非常糟糕的主意.
但是,某些情况保证这样做:
CLOSE_WAIT或最终处于该TIME_WAIT状态.TIME_WAIT(close()从服务器端调用时),因为这可能会阻止服务器获取新客户端连接的可用端口重启后.CLOSE_WAIT试图将数据传送到卡住的终端端口,但如果RST要丢弃挂起的数据,将正确地重置卡住的端口."我会推荐这篇长篇文章,我认为这篇文章能很好地回答你的问题.
caf*_*caf 72
将SO_LINGER超时设置为零的典型原因是避免处于该TIME_WAIT状态的大量连接,从而占用服务器上的所有可用资源.
当干净地关闭TCP连接时,启动关闭的结束("主动关闭")最终会在连接处TIME_WAIT停留几分钟.因此,如果您的协议是服务器启动连接关闭的协议,并且涉及大量短期连接,那么它可能容易受到此问题的影响.
但这不是一个好主意 - TIME_WAIT存在的原因(确保来自旧连接的杂散数据包不会干扰新连接).如果可能的话,最好将协议重新设计为客户端启动连接的协议.
Len*_*ate 16
当"间隔"打开但超时为零时,TCP堆栈不会等待在关闭连接之前发送待处理数据.由于这种情况,数据可能会丢失,但是通过这种方式设置逗留,您接受这个并要求立即重置连接而不是优雅地关闭.这导致发送RST而不是通常的FIN.
感谢EJP的评论,详情请见此处.
小智 6
是否可以安全地删除代码中的延迟取决于应用程序的类型:是“客户端”(打开TCP连接并首先主动关闭它)还是“服务器”(侦听TCP打开和关闭)?在另一方发起关闭后将其关闭)?
如果您的应用程序具有“客户端”的风格(首先关闭),并且您启动和关闭了与不同服务器的大量连接(例如,当您的应用程序是监视应用程序,监督大量不同服务器的可达性时)有一个问题,您的所有客户端连接都停留在TIME_WAIT状态。然后,我建议将超时时间缩短为小于默认值的值,以便仍然正常关闭,但更早地释放客户端连接资源。我不会将超时设置为0,因为0不会通过FIN正常关闭,但会通过RST中止。
如果您的应用程序具有“客户端”的风格,并且必须从同一服务器中获取大量小文件,则不应为每个文件启动新的TCP连接,而在TIME_WAIT中最终导致大量客户端连接,但是保持连接打开并通过同一连接获取所有数据。流浪者选项可以并且应该删除。
如果您的应用程序是一个“服务器”(对同伴的关闭响应为第二关闭),则在close()上,您的连接将正常关闭,并且由于不进入TIME_WAIT状态,因此资源被释放。不应使用流连忘返。但是,如果您的服务器应用程序具有检测长时间闲置(定义为“ long”)的非活动打开连接的管理过程,则可以从您的侧面关闭该非活动连接-将其视为一种错误处理-异常中止关闭。这是通过将linger超时设置为0来完成的。close()然后将向客户端发送RST,告诉他您很生气:-)
| 归档时间: |
|
| 查看次数: |
118682 次 |
| 最近记录: |