我知道在这方面有很多 SE 问题,我相信在谈到这一点之前,我已经阅读了尽可能多的问题。
“服务器端TIME_WAIT”是指在服务器端启动其 close() 的服务器端套接字对的状态。
我经常看到这些听起来自相矛盾的陈述:
TIME_WAIT是无害的TIME_WAIT我发现这个矛盾的原因是因为TIME_WAIT在客户端可能是一个问题——客户端可能会耗尽可用端口,所以本质上,上面建议将负担转移TIME_WAIT到可能有问题的客户端,从服务器端,这不是问题。
客户端TIME_WAIT当然只是少数用例的问题。大多数客户端 - 服务器解决方案将涉及一台服务器和许多客户端,客户端通常不会处理足够大的连接量以至于不会成为问题,即使他们这样做,也有一些“理智”的建议(而不是SO_LINGER与0超时,或tcp_tw的sysctl插手)作战客户端TIME_WAIT通过避免创建连接过多过快。但这并不总是可行的,例如对于如下类的应用程序:
另一方面,我什至不明白服务器端TIME_WAIT有什么帮助。原因TIME_WAIT甚至存在,是因为它可以防止将陈旧的TCP片段注入它们不再属于的流中。对于客户端,TIME_WAIT它是通过简单地使无法创建与ip:port此陈旧连接可能具有的相同对的连接(使用的对被 锁定TIME_WAIT)来实现的。但是对于服务器端,这是无法阻止的,因为本地地址将具有接受端口,并且始终相同,并且服务器不能(AFAIK,我只有经验证明)仅仅因为传入的对等点将创建与套接字表中已存在的地址对相同的地址对。
我确实编写了一个程序,显示服务器端 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
Run Code Online (Sandbox Code Playgroud)
因此,对于服务器端TIME_WAIT,完全相同的端口对上的连接可以立即并成功地重新建立,而对于客户端TIME-WAIT,在第二次迭代时connect()理所当然地失败了
总而言之,这个问题有两个方面:
TIME_WAIT真的什么都不做,只是因为RFC需要它而保持这种状态吗?TIME_WAIT是因为服务器没用吗?在TCP术语中,服务器端指的是套接字处于 LISTEN 状态的主机。
RFC1122允许处于TIME-WAIT状态的套接字在某些条件下接受新连接
Run Code Online (Sandbox Code Playgroud)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。我希望套接字上也必须有一个匹配的被动打开(套接字处于侦听状态)。
Active OPEN(客户端连接调用)没有此类异常,并且根据RFC793 ,当套接字处于 TIME-WAIT 时必须给出错误。
我对客户端(在 TCP 术语中,执行主动打开即连接的主机)启动关闭的建议的猜测与您的建议大致相同,在常见情况下,它将 TIME-WAIT 套接字传播到更多主机上,这些主机有丰富的资源插座。在常见情况下,客户端不会发送会在服务器上重用 TIME-WAIT 套接字的 SYN。我同意应用此类建议仍然取决于用例。