我正在与一些蹩脚的(自定义)服务器软件,它不接受它的连接正确(由Java程序员谁从来没有触及套接字,更不用说线程)的Java写的。 我的猜测是线程在客户端线程中正确接受套接字之前即将死亡。 我不能确定,因为软件目前被重新实现,所以它并不重要。 旧版本必须保持运行,直到新版本上线,尽可能可靠,但没有花费在debugging旧代码库上的时间和金钱。
该错误显示在下面的netstat输出中; 一些连接永远不会从内核转移到使用空间(这就是我对此的解释,更好的解释是受欢迎的):
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name tcp6 228 0 192.0.2.105:1988 46.23.248.10:7925 ESTABLISHED - tcp6 0 0 192.0.2.105:1988 221.130.33.37:9826 ESTABLISHED 14741/java tcp6 0 0 192.0.2.105:1988 46.23.248.2:5867 ESTABLISHED 14741/java tcp6 2677 0 192.0.2.105:1988 221.130.33.37:15688 ESTABLISHED - tcp6 3375 0 192.0.2.105:1988 221.130.33.36:3045 ESTABLISHED - tcp6 14742 0 192.0.2.105:1988 46.23.248.17:4679 ESTABLISHED - tcp6 774 0 192.0.2.105:1988 212.9.19.73:36064 ESTABLISHED - tcp6 92 0 192.0.2.105:1988 46.23.248.19:7164 ESTABLISHED - tcp6 0 0 192.0.2.105:1988 46.23.248.21:6322 ESTABLISHED 14741/java tcp6 0 0 192.0.2.105:1988 221.130.39.216:13937 ESTABLISHED 14741/java tcp6 3051 0 192.0.2.105:1988 211.139.145.104:31239 ESTABLISHED - tcp6 246 0 192.0.2.105:1988 46.23.248.10:5458 ESTABLISHED - tcp6 618 0 192.0.2.105:1988 212.9.19.73:20209 ESTABLISHED - tcp6 1041 0 192.0.2.105:1988 46.23.248.18:7424 ESTABLISHED - tcp6 0 0 192.0.2.105:1988 46.23.248.10:5065 ESTABLISHED 14741/java
发生这种情况时,客户重新连接,他们倾向于工作。 但是,直到他们进入相当长的暂停时间,他们才会自行重新连接。 由于自定义的全双工协议在其当前版本中并不包含客户端发送的任何数据,而后者也不期望从服务器收到任何有规律的传入请求,因此客户端可以愉快地发送数据直到内核接收队列已满。 在服务器(内核)方面,应该可以检测旧套接字,因为客户端定期发送数据。
所以,假设我对这个问题的解释是正确的,那么我想知道的是,如果有一个内核参数,我可以调整这个参数,使得内核在没有及时从用户空间读取的情况下丢弃/closures与RST的TCP连接方式。
更好的解释这里发生的事情也是受欢迎的。
您可以尝试将TCP keepalive调整为更短的值。 默认情况下,在Keepalive启动之前,连接可以闲置两个小时。
究竟应该使用什么值取决于应用程序的function,用户期望的function以及它们如何与之交互。
我想答案是否定的。
通过更换有问题的软件解决了这个问题,但是仍然有一些想法。