我在linux上运行特定程序有时会崩溃。如果在此之后快速打开它,它将监听套接字49201,而不是第一次监听49200。 netstat揭示49200处于TIME_WAIT状态。

是否存在可以运行以立即迫使套接字移出TIME_WAIT状态的程序?

评论

如果您由于“服务器上的TIME_WAIT太多”而在这里,只需跳过前三个答案即可避免出现问题,而无需回答。

我接受了第四个答案,所以它应该现在排在第一位

#1 楼

实际上,有一种方法可以杀死连接-killcx。他们声称它可以在连接的任何状态下工作(我尚未验证)。您需要了解通信发生的接口,但默认情况下它似乎是eth0。

更新:另一个解决方案是一些Linux发行版的存储库中附带的cutter。

#2 楼

/etc/init.d/networking restart


让我详细说明。传输控制协议(TCP)设计为在两个端点(程序)之间的双向,有序且可靠的数据传输协议。在这种情况下,术语“可靠”表示如果中间丢失,它将重新传输数据包。 TCP通过发回针对从对等方接收到的单个或一系列数据包的确认(ACK)数据包来保证可靠性。 RFC 793定义TIME-WAIT状态如下:


TIME-WAIT-表示等待足够的时间以确保远程TCP传递。收到其连接终止请求的确认。


请参见以下TCP状态图:


TCP是双向通信协议,因此在建立连接时,客户端和服务器之间没有区别。另外,任何一个都可以调用退出,并且两个对等方都需要同意关闭以完全关闭已建立的TCP连接。

让我们第一个调用退出作为活动的更紧密的退出被动的接近者。当主动关闭器发送FIN时,状态进入FIN-WAIT-1。然后,它接收到发送的FIN的ACK,状态进入FIN-WAIT-2。一旦它也从被动关闭器接收到FIN,主动关闭器将ACK发送到FIN,状态进入TIME-WAIT。如果被动关闭器未收到到第二个FIN的ACK,它将重新传输FIN数据包。RFC793将TIME-OUT设置为最大段生存时间的两倍,即2MSL。由于MSL,数据包可以在Internet上徘徊的最长时间设置为2分钟,而2MSL为4分钟。
由于没有ACK确认,因此如果主动关闭器正确地遵循TCP / IP协议,则主动关闭器只能等待4分钟,以防万一被动发送方没有收到FIN的ACK(理论上) 。

实际上,丢失的数据包可能很少见,如果全部发生在LAN或单个计算机中,则非常罕见。

要逐字回答“如何在TIME_WAIT中强制关闭套接字?”的问题,我仍然会坚持原来的回答:

/etc/init.d/networking restart


实际上,我将对其进行编程,以便使用WMR提到的SO_REUSEADDR选项忽略TIME-WAIT状态。 SO_REUSEADDR到底是做什么的?


此套接字选项告诉内核
即使该端口正忙(在TIME_WAIT状态下),继续执行并
无论如何都可以重用它。如果很忙,但又处于另一种状态,您仍然会得到一个已经在使用中的地址错误。如果您的服务器已关闭
,然后立即重新启动
,而套接字在其端口上仍处于活动状态,则
很有用。您应该意识到,如果
出现任何意外数据,可能会
混淆您的服务器,但是虽然这是可能的,但不可能。


评论


好的答案,但不是他问题的正确答案。重新启动网络可以,但是重新启动后可以,因此不正确。

–克里斯·黄·利弗(Chris Huang-Leaver)
09年8月6日在17:03

@Chris Huang-Leaver,问题是“您是否可以运行一个程序来立即迫使套接字移出TIME_WAIT状态?”如果重新启动可以考虑运行程序,那么它也是正确的答案。您为什么认为这不对?

– Eugene Yokota
09年8月6日在17:59

WMR有最有用的答案(当我遇到此类问题时,这就是我要做的事情)。重新启动网络太过激烈,无法解决,而且可能比等待超时要花费更长的时间。对他的问题的正确答案是“否”,但这样一来,您就不能输入两个字母来回答问题了:-

–克里斯·黄·利弗(Chris Huang-Leaver)
09年9月2日在11:23

好的,下次在SIGTERM上挂起某些进程时,我将砸碎计算机,而不是修复它。

– Longpoke
2010年5月13日在16:13

通用的是“重启网络服务”。 /etc/init.d/networking的特定位置是特定于平台的(Debian?),因此对于其他系统,精确的命令行将有所不同(有时相当根本)。我同意其他评论者的观点,这似乎严重过头,并且显然对任何不相关的网络服务都具有破坏性。

–tripleee
19-6-26在8:22



#3 楼

我不知道您是否具有正在运行的特定程序的源代码,但是如果是这样,您可以通过setsockopt(2)设置SO_REUSEADDR,即使套接字处于TIME_WAIT状态,它也允许您绑定到相同的本地地址(除非该套接字正在积极侦听,请参阅socket(7))。

有关TIME_WAIT状态的更多信息,请参见Unix套接字常见问题解答。

评论


但是我没有得到已经绑定的错误。当我再次执行程序时,它在post(123456)中侦听,我也可以看到系统正在显示该端口的TIME_WAIT,但仍然可以连接。为什么?

–贾巴尔(Jayapal Chandran)
2010-09-27 8:26

即使使用SO_REUSEADDR,仍然可能会出现“地址已在使用中”错误。有关详细信息,请参阅hea-www.harvard.edu/~fine/Tech/addrinuse.html。

–姚景国
13年6月27日在2:16

@WMR SO_REUSEADDR不会“关闭”套接字。它仅使您可以重用那些已经打开的文件。因此问题仍然是“如何在TIME_WAIT中强制关闭套接字?”

–起搏器
16年1月23日在4:15



这是正确的答案,但问题并不完全正确。至少可以很好地解决我的问题(不像重启整个网络那样断开所有其他连接)。

– V-Mark
18/12/29在11:08



SO_REUSEADDR将让bind()继续进行;但是,如果您随后想要监听该套接字,则listen()将返回EADDRINUSE。换句话说,此答案可能会帮助使用临时端口的客户端软件,但不能解决服务器软件的问题。

–将
19年6月16日在4:06

#4 楼

据我所知,除了在程序中编写更好的信号处理程序外,没有办法强制关闭套接字,但是有一个/ proc文件来控制超时时间。该文件为

/proc/sys/net/ipv4/tcp_tw_recycle


,您可以通过以下方式将超时设置为1秒:

echo 1 > /proc/sys/net/ipv4/tcp_tw_recycle 


但是,此页面包含有关设置此变量时可能出现的可靠性问题的警告。

还有一个相关文件

/proc/sys/net/ipv4/tcp_tw_reuse


,该文件控制TIME_WAIT套接字可以重复使用(大概没有任何超时)。

顺便说一句,内核文档警告您在没有“技术专家的建议/要求”的情况下不要更改这两个值。我不是。

必须编写程序才能尝试绑定到端口49200,如果该端口已在使用中,则将其递增1。因此,如果您可以控制源代码,则可以将此行为更改为等待几秒钟,然后在同一端口上重试,而不是递增。

评论


认为后两个示例应该是s / rw / tw /我要编辑,但缺乏足够的代表。

– blueshift
09年10月6日在3:26

取自内核文档:警告。 tcp_tw_recycle和tcp_tw_reuse都可能导致问题。在不了解正在使用的节点或启用了该参数的节点之间的节点之间的网络拓扑的情况下,都不应该启用。由于设置的原因,通过了解TCP连接状态的节点(例如防火墙,NAT或负载平衡器)进行的连接可能会开始丢弃帧。连接数量足够多时,该问题将变得明显。

– jfarrell
2010-2-22在18:54

将其设置为1可以用于将来的连接,但是那些当前已经打开的连接又如何呢?

–起搏器
16年1月23日在4:16

#5 楼

另一种选择是使用SO_LINGER选项,且超时值为0。这样可以避免TIME_WAIT状态,并且可能更适合某些用途。

评论


它还会丢失任何仍在传输的出站数据,并且可能在另一端引起错误。不建议。

–user207421
2011年3月31日在9:46

@EJP尽早失败几乎总是正确的选择。网络是不可靠的,而战斗会使事情变慢。崩溃的应用程序无法假设任何数据都能安全地将其识别出来。

–东武
2014年12月9日在2:06

实际上,我会在另一端是一个有问题的嵌入式工业总线网关的任何一天建议这样做,该网关通过TCP实现其自己的应用程序层可靠传输,在这种传输中,除非接收到RST,否则该连接将永远无法关闭,从而填充该网关的连接限制。那里。我给了你一个非常具体而真实的例子,可悲的是,它需要诉诸于这种黑客。

– andyn
15年5月28日在18:33

@Tobu Networking不可靠,但是TCP试图做到这一点,而且变得更糟并不意味着可以做得更好,让TCP做好其工作并不意味着要“战斗”。

–user207421
18-3-22在2:45

#6 楼

一种替代解决方案是拥有一些可靠的代理或端口转发软件,该软件侦听端口49200,然后使用不同的端口将连接转发至您的较不可靠程序的多个实例之一。
顺便说一下,您连接的端口很高。您可以尝试使用0-1024范围上方的未使用的。您的系统不太可能将较低的端口号用作临时端口。

#7 楼

TIME_WAIT是套接字编程客户端服务器体系结构中最常见的问题。
等待几秒钟是最佳的解决方案。
对于实时应用程序,他们需要服务器必须立即启动
他们的SO_REUSEADDR选项。