服务器端的“ TIME_WAIT”如何真正起作用?


11

我知道有很多关于SE的问题,在达到这一点之前,我相信我阅读了很多重要的问题。

“服务器端TIME_WAIT”是指在服务器端启动了close()的服务器端套接字对的状态。

我经常看到这些与我矛盾的陈述:

  1. 服务器端TIME_WAIT无害
  2. 您应该设计网络应用程序,让客户端启动close(),因此让客户端承担 TIME_WAIT

我发现这一矛盾的原因是TIME_WAIT,在客户端上可能会出现问题-客户端可能会用尽可用端口,因此从本质上讲,以上建议将负担TIME_WAIT从客户端转移到客户端。服务器端,这不是问题。

TIME_WAIT对于有限的用例,客户端当然只是一个问题。大多数客户端-服务器解决方案都将涉及一台服务器和许多客户端,客户端通常无法处理足够多的连接,因此即使出现问题,也有许多建议可以“合理地”解决(而不是SO_LINGER使用0超时或与tcp_tw sysctls进行干预)TIME_WAIT通过避免太快地创建太多连接来打击客户端。但这并不总是可行的,例如对于以下应用程序类:

  • 监控系统
  • 负载发生器
  • 代理

另一方面,我什至根本不了解服务器端如何提供TIME_WAIT帮助。原因TIME_WAIT甚至在那里,是因为它防止将过时的TCP片段注入到它们不再属于的流中。对于客户端TIME_WAIT,只需简单地使其无法与ip:port该过时的连接建立相同的连接就可以完成连接(使用的对由锁定TIME_WAIT)。但是对于服务器端而言,这是无法避免的,因为本地地址将具有接受端口,并且始终保持相同,并且服务器(仅因经验证明,我仅凭经验证明)无法拒绝连接,原因仅在于传入对等方将创建套接字表中已经存在的相同地址对。

我确实编写了一个程序,该程序显示服务器端TIME-WAIT被忽略。而且,由于测试是在127.0.0.1上完成的,因此内核必须具有一个特殊位,甚至可以告诉它是服务器端还是客户端(因为否则,元组将是相同的)。

来源:http : //pastebin.com/5PWjkjEf,已在Fedora 22(默认网络配置)上测试。

$ gcc -o rtest rtest.c -lpthread
$ ./rtest 44400 s # will do server-side close
Will initiate server close
... iterates ~20 times successfully
^C
$ ss -a|grep 44400
tcp    TIME-WAIT  0      0            127.0.0.1:44400         127.0.0.1:44401   
$ ./rtest 44500 c # will do client-side close
Will initiate client close
... runs once and then
connecting...
connect: Cannot assign requested address

因此,对于服务器端TIME_WAIT,可以立即成功地重建完全相同的端口对上的连接,对于客户端TIME-WAIT,在第二次迭代中connect()正确地失败

总而言之,这个问题有两个方面:

  • 服务器端TIME_WAIT真的不做任何事情,而是按照RFC要求这样做了吗?
  • 是因为服务器TIME_WAIT无用,建议客户端启动close()的原因?

除非您只有1个客户端,否则您不会用尽端口。客户端/服务器IP的每种组合都有65535个端口。从1.2.3.4:1111开始的连接与4.3.2.1:1111不同。中的每个连接只需要占用几个字节的内存TIME_WAIT
Marki555

Answers:


1

TCP术语来说,服务器端在这里是指套接字处于LISTEN状态的主机。

RFC1122允许处于TIME-WAIT状态的套接字在某些情况下接受新连接

        When a connection is closed actively, it MUST linger in
        TIME-WAIT state for a time 2xMSL (Maximum Segment Lifetime).
        However, it MAY accept a new SYN from the remote TCP to
        reopen the connection directly from TIME-WAIT state, if it:

有关条件的确切详细信息,请参见RFC1122。我希望套接字上还必须有一个匹配的被动OPEN(侦听状态下的套接字)。

根据RFC793,活动OPEN(客户端连接调用)没有这种异常,并且当套接字处于TIME-WAIT时必须发出错误。

我对启动关闭的客户端(以TCP术语表示执行主动OPEN即连接的主机)的建议与您的建议大致相同,在通常情况下,它将在更多的主机上分配TIME-WAIT套接字,而这些主机上有大量资源插座。在通常情况下,客户端不会发送将在服务器上重用TIME-WAIT套接字的SYN。我同意应用这种建议仍然取决于用例。


0

可能是TIME-WAIT实际做什么的最清楚的例子,更重要的是为什么它很重要。它还说明了为什么要避免在Linux计算机上使用某些“专家”技巧来“减少” TIME-WAIT。


仍然没有解释,当客户机- >服务器发起连接发生了什么,以及服务器有对处于TIME_WAIT锁定
帕维尔Veselov

请参阅stackoverflow.com/questions/1490196/…-答案就是您要找的东西。
库什希尔

0

tcp会话由tupple标识(sourceIP,sourcePort,destIP,destPort)。因此,TIME_WAIT确实适用于每个tcp连接。

关于关闭方面,在某些情况下,从客户端关闭可以减少服务器上的TIME_WAIT套接字,从而略微减少内存。如果套接字空间可能已用完(由于临时端口耗尽)(例如,贪婪的客户端与同一台服务器有许多连接),则应从任一方面解决此问题。


请解释; 当您询问服务器端TW是否执行任何操作时,您想知道在TW期间是否可以重用同一连接。答案是否定的,因为该连接由tupple定义,位于服务器的tcp表中。如果客户端尝试尽快打开相同的连接,它将收到RST,有效地拒绝了tcp连接。顺便说一下,来自Khushil的文章非常具有描述性。
2015年

非常抱歉,您的回答确实回答了问题,我看错了,并撤回了我的评论。但是,这似乎也不正确,因为我的代码似乎证明没有服务器端的保护TIME_WAIT(我用该信息更新了问题)。@Khushil的参考没有TIME_WAIT足够详细地介绍服务器端情况。
Pawel Veselov

-2

您永远无法确定使用不可靠的协议是从对等设备收到了最后一条消息,因此危险的是假设对等设备突然挂断了电话。TCP协议的主要缺点是只能同时打开大约65000个端口。但是解决此问题的方法将是移至服务器场,该服务器场可通过负载进行扩展,而不是通过快速回收端口号来更好地进行扩展。在客户端,如果它是基本工作站,则端口用完的可能性很小。


非常抱歉,但这无法回答我的问题。
Pawel Veselov
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.