java检测不可靠网络上的TCP丢失
我正在一个不可靠的无线网络(自制)上做一些实验,使用非常基本的javasocket编程在终端节点之间来回传输消息
设置如下所示:
节点A---中继节点---节点B
我经常遇到的一个问题是,不知何故,连接断开了,节点A或B都不知道链路已断开,但仍在继续传输数据。TCP连接也不会超时。我添加了一条心跳消息,它会在一段时间后导致超时,但我仍然想知道TCP没有超时的根本原因是什么
以下是我在设置socket时启用的选项:
channel.socket().setKeepAlive(false);
channel.socket().setTrafficClass(0x08); // for max throughput
这种行为很奇怪,因为它与我使用有线网络时完全不同。在有线网络上,我可以通过拔出以太网线来模拟断开的连接,但是,一旦我重新插入网线,连接将重新启动,消息将再次开始传递
在无线网络上,连接永远不会重新建立,一旦它悄无声息地消失,消息就永远不会恢复
是否有其他未知的java实现或socket设置我可以使用,还有,为什么我首先看到这种行为
是的,在任何人说什么之前,我知道TCP不是不可靠网络的首选,但在这种情况下,我想确保没有数据包丢失
# 1 楼答案
TCP协议被设计成安静的。RFC要求保持心跳频率不超过2小时。除非你能控制两端的系统来更改默认的2小时心跳(有时需要重建内核),否则你必须在自己的应用程序中添加心跳
如果发送心跳信号,它仍然需要等待重新传输超时,这取决于RTT。在高延迟网络上,超时可能非常高,但应该在几分钟内
您会在本地网络上收到通知,因为系统可以检测链路断开状态并断开该网络上的所有连接
顺便说一句,您希望将Keepalive设置为TRUE,而不是false。有了Keepalive,你至少会心跳缓慢
# 2 楼答案
在OSI 7层模型中,前两层是物理层和数据链路层。在有线以太网上运行数据链路协议的物理硬件可以检测何时拉动电缆。你的无线硬件和相应的协议,可能没有那么多。如果layer1/2没有发出断开连接的信号,TCP堆栈就无法超时
# 3 楼答案
定义“永不”
我希望你最终会收到一封邮件通知。你可能只是希望比预期的更早得到通知。TCP堆栈将重新传输其未获得ACK的段,每次尝试重新传输前的超时时间将在每次重新传输时加倍。取决于堆栈如何确定何时重新传输,在堆栈决定连接断开之前,它可能会比您预期的时间长,然后才会让您知道
看这里:http://www.ietf.org/rfc/rfc2988.txt,这里:http://msdn.microsoft.com/en-us/library/ms819737.aspx,等等
你已经习惯了有线网络,在这个网络中,驱动程序可以通知更高级别的层连接已被物理破坏。如果你将有线网络配置为通过路由器进行路由,然后故意设置为不正确路由,那么你可能会看到类似的行为