我试图找出Java TCP套接字当前是否已连接,以下似乎只是告诉我套接字是否已经连接 - 而不是它当前是否仍然连接.
socket.isConnected();
Run Code Online (Sandbox Code Playgroud)
任何帮助表示感谢,谢谢.
更新:如果你想节省冗长的序言,请跳至答案.
TCP/IP连接KeepAlives指定为每两个小时至少一次:http://tools.ietf.org/html/rfc1122#page-101.问题是这是写于1989年,并担心发送额外的KeepAlive数据包的成本!然而,仍然是默认时间,大多数操作系统根据规范在一段时间不活动后将KeepAlives发送到连接的套接字!当然,现在大多数连接超时之前的方式如果不活动,如果通过Internet连接连接到对等设备之前没有你的知识方式(尽管设置的超时高于那个 - 我怀疑因为中间的路由器表不打扰保持它活着 - 我总是想知道泄露的最后一条消息在哪里... 更新:原因是可能位于您或远程主机端的"路由器"处于"有状态"且可识别连接并在一段时间不活动后断开连接 - 您通过Internet访问的路由器无法断开连接 - 他们不关心 - 数据包只是发送到必须去的地方).所以我看到了两种常见的解决方案来保持互联网上的连接:
1)忽略(编辑:已经向我指出这不是无视规范它只是改变默认值)规范并将系统范围的KeepAlive间隔改为低于2小时,或2)实现自己的'KeepAlive'系统定期轮询对等体.
无论哪种方式; 什么是合适的时间段(发送KeepAlive的不活动时间)?我已经看到从1秒到默认2小时的所有内容.似乎这个数字是从拇指中吸出的......如果我有一个客户端应用程序从世界上任何地方连接什么是安全合理的时期(我想要一个持久的连接)?通过互联网连接到世界另一端的同伴很多跳,连接在301秒后死亡(尽管你在尝试发送东西时只知道它)所以将周期设置为300秒似乎是神奇的数字 - 我在死亡前获得了KeepAlive 1秒钟 - 这段时间从来没有让我失望过..但是它安全吗?
编辑:这个特殊的连接我实现在C#3.0所以代码在欢迎.
如何检测 TCP 连接中的死链接?当有人拉扯网线、关闭网络接口、打开 WiFi 或者像我这样......拔掉电源时,就会发生死链接。
Keep-alive 只对客户端有效,对服务器无效。
服务器只是接收数据,从不发送,因此使用 TCP_USER_TIMEOUT 将不起作用,因为发送 q 将始终为空。
我不想实现速度损失的应用层协议原因。(不再是零拷贝)
有效的一件事是发送 oob 数据,但因为你不应该再使用它了......
在下面编写的测试之后,您将看到客户端连接将在预期的短时间内关闭。 但是服务器会认为它已连接,永远......到目前为止等了3小时......
到目前为止,我在 3.13(Kubuntu) 和 3.18(OpenWrt) Linux 内核上对此进行了测试。这是一个错误吗?到目前为止,我已经阅读了很多 tcp/socket 编程书籍......根本没有帮助。请伙计们我需要你的帮助:)
我正在使用异步/非阻塞 io (epoll),因此发送和 rcv 超时也不起作用。
UPDATE2:现在有 x64/x86 的剪切源
添加:我以为我可以通过 epoll 事件捕获错误。
但是如果发生错误,我是否需要询问套接字?
#define MAX_EVENTS 64
#define CON_RETRY_TIMEOUT 10 /* time to wait in sec until next connect attempt */
#define CON_TIMEOUT 10 /* time in sec after which stop trying to connect */
#define CON_IDLE 10 /* time in sec after which …Run Code Online (Sandbox Code Playgroud)