2011-07-13 29 views
0

背景/平臺:TcpClient的持續發送了一段時間,即使沒有連接

.NET 4/C#

我有一個C#TcpClient連接到以太網一個嵌入式設備。 我正在使用兩個定時器 - 一個用於將接收到的數據存儲在本地Queue<MyMessage>中,另一個用於通過TCP將另一個Queue<MyMessage>的數據發送到嵌入式設備。這兩種方法每個都運行200 ms併發送/讀取他們必須發送/讀取的任何內容。

還有一個定時器發送保持活動數據包every second(目前僅用於調試目的)。

情景/問題

建立連接後,嵌入式設備開始一些數據發送給我的TcpClient。這按預期工作(參見下面的消息日誌)。但是,我關閉該設備(所以它根本不工作)。這意味着它甚至無法正確關閉TCP。但沒關係。我想測試一下如果像這樣發生在真實情況下會發生什麼。

但是,即使服務器(設備)不再在線,TcpClient仍會繼續發送數據。

下面是發送(使用NetworkStream.Write)的代碼:發送另一個45-50秒,不斷去,最後它打破

while (messagesToSend.Count > 0) 
{ 
    MyMessage msg = messagesToSend.Dequeue(); 
    clientStream.Write(msg.Data, 0, msg.Data.Length); 

    Debug.WriteLine(DateTime.Now.ToString() + " Sent: " + msg.MessageID); 
} 

。 這些是TcpClient的和的NetworkStream

client.LingerState = new LingerOption(true, 0); 
client.NoDelay = true; 
client.SendTimeout = 3000; 
clientStream.WriteTimeout = 3000; 

設置在這裏的選項是調試輸出:

16:32:02 Connecting 
16:32:02 Authorizing 
16:32:02 Sent: 255 
16:32:02 Sent: 0 
16:32:02 Authorized 
16:32:02 Connected 
16:32:02 Received: 255 
16:32:02 Received: 226 
... 
... some regular communication here 
... 
16:32:06 Received: 251 
16:32:06 Sent: 0 
16:32:07 Received: 251 
16:32:07 Sent: 0   // At this point I have turned off the device 
16:32:08 Sent: 0 
16:32:09 Sent: 0 
... 
... every second the same message 
... 
16:32:54 Sent: 0 
16:32:55 Sent: 0 
16:32:56 Sent: 0 
16:32:57 Unable to write data to the transport connection: An established connection was aborted by the software in your host machine. 
16:32:57 CommunicationError 

它爲什麼花了這麼長時間的連接來實現,它被關閉?如果主機沒有響應,NetworkStream.Write不應該立即失敗?

如何到檢測到設備的電源被切斷,連接不再有效?

回答

1

你不能。如果你之間有交換機/路由器,你會如何檢測到這一點?您的電腦仍然完全連接。

TCP/IP以這種方式工作。有幾個重新發送(通常會增加超時)任何未被接收方確認的數據包。超時值和重發次數是特定於您的tcp堆棧/操作系統的實現。

TcpClient.SendTimeout屬性僅控制將數據進一步發送到流的時間。

在調用Write方法後,底層套接字返回實際發送到主機的字節數。 SendTimeout屬性決定了TcpClient在收到返回的字節數之前等待的時間。如果超時在Send方法成功完成之前超時,則TcpClient將引發一個SocketException。默認情況下沒有超時。

+0

所以基本上,知道連接是否仍然有效的唯一方法是服務器(本例中的設備)每XY秒發送一次自定義協議消息,然後如果我沒有收到它一個XY(或多一點)秒我知道出了什麼問題?我知道,當連接失敗時,Read操作將返回0(因爲接收到0字節),但它似乎只能在Read上工作,而不能在Write上工作。 –

+0

不是。數據包仍然可以在這裏和這裏之間緩衝。唯一可以衡量的是rtt(往返時間)。如果你真的想要構建你正在描述的東西,那麼切換到不執行重發的udp(等等)。 – sisve

相關問題