2010-05-17 16 views
3

我做了一个不可靠的无线网络进行一些试验用非常简陋的Java Socket编程来传输邮件前后端节点之间(自家酿制的)。检测TCP差在不可靠的网络

的设置如下:

节点A ---中继节点---节点B

的一个问题,我不断地跑入现象的原因是连接滴出既不节点A或B知道该链接已经死亡,但仍然继续传输数据。 TCP连接也不超时。我在心跳消息中添加了一段时间后会导致超时,但我仍然想知道TCP为什么不超时的根本原因。

下面是我设立一个插座时启用的选项:

channel.socket().setKeepAlive(false); 
channel.socket().setTrafficClass(0x08); // for max throughput 

此行为是奇怪的,因为它比当我有一个有线网络完全不同。在有线网络中,我可以通过拔出以太网电缆来模拟断开的连接,但是,一旦将电源线插回,连接就会重新建立,并且信息会再次通过。

在无线网络中,连接不会重新建立,一旦它静静地死去,消息从来没有恢复。

有一些其他未知的java implentation或设置,我可以使用,另外,为什么我看到摆在首位此行为的插座?

是的,任何人说任何事之前,我知道,TCP是不是在不可靠的网络的优先停留的选择,但在这种情况下,我想,以确保没有数据包丢失。

+0

可能不可用,除非你想要某些平台特定的,由于TCP实现的本质。 – WhirlWind 2010-05-17 19:28:56

回答

2

TCP协议被设计为安静。 RFC要求Keepalive心跳不超过2小时。除非您可以控制两端的系统来更改默认的2小时心跳(有时需要重建内核),否则必须在自己的应用中添加心跳。

如果您发送心跳,它仍然需要等到重传的时间,这取决于往返时间。在高延迟网络中,超时时间可能很长,但应该在几分钟之内。

您在本地网络上收到通知,因为系统可以检测到链接关闭状态并删除该网络上的所有连接。

顺便说一句,你要设置Keepalive为TRUE,而不是false。随着Keepalive,你至少会得到缓慢的心跳。

+0

就是这样,终端节点A仍然试图在整个时间内发送到结束节点B,但是我的channel.isConnected()永远不会变为false(我在尝试发送消息之前在单独的线程中测试它)。这是20多分钟的时间,在这之前不应该消息超时了吗?此外,我在尝试发送消息时从未收到任何异常。 – 2010-05-17 19:35:46

+0

你知道你的RTT(往返时间)是什么?计算接收超时是非常严重的事情,请参阅http://www.ietf.org/rfc/rfc2988.txt,如果RTT非常大,则可能超过20分钟。 – 2010-05-17 19:40:56

+0

RFC不需要keepalive,但它需要*如果存在*它*默认*至少两个小时。 – EJP 2017-04-26 21:17:18

2

在OSI 7层模型中,前两层是物理和数据链接。在有线以太网上运行数据链路协议的物理硬件可以检测电缆何时被拉出。您的无线硬件和相应的协议可能不是那么多。如果layer1/2的东西没有通知它断开连接,那么TCP堆栈不能做任何事情超时。

+0

有趣的是,我将研究可能实现的信令方面 – 2010-05-17 19:37:29

+0

不幸的是TCP/IP不使用OSI 7层模型。我不知道人们为什么一直在谈论它。让它安息吧。 – EJP 2017-04-26 21:18:12

1

定义'从不'?

我希望你最终会收到发送失败通知。您可能只是希望早日得到通知。 TCP堆栈将重传没有得到ACK的段,并且重传之前的每次尝试重发之前的超时时间会在每次重传时加倍。取决于堆栈如何进行重传的时间,堆栈可能会比预期的时间长,因此堆栈会判断连接中断,只有这样才会让您知道。

在这里看到:http://www.ietf.org/rfc/rfc2988.txt,在这里:http://msdn.microsoft.com/en-us/library/ms819737.aspx

你已经习惯了一个带有有线网络中的驱动程序可以通知连接已经破物理更高层次层。如果你要配置一个有线网络通过路由器进行路由,那么你故意设置路由不正确,那么你可能会看到类似的行为......