我知道有很多关于SE的问题,在达到这一点之前,我相信我阅读了很多重要的问题。
“服务器端TIME_WAIT
”是指在服务器端启动了close()的服务器端套接字对的状态。
我经常看到这些与我矛盾的陈述:
- 服务器端
TIME_WAIT
无害 - 您应该设计网络应用程序,让客户端启动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()的原因?
TIME_WAIT
。