2010-05-17 62 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

你已經習慣了一個帶有有線網絡中的驅動程序可以通知連接已經破物理更高層次層。如果你要配置一個有線網絡通過路由器進行路由,那麼你故意設置路由不正確,那麼你可能會看到類似的行爲......