簡體   English   中英

TCPClient流不規則?

[英]TCPClient stream irregularities?

我有一個TCPClient,它創建一個我在DataAvailable時讀取的流。

每隔20秒!DataAvailable我用ACK消息ping套接字以防止流關閉。

但我似乎得到了好壞參半的結果。 似乎每隔一次我打開流(基本上重啟我的服務)我得到傳輸錯誤。

這是我的Connect功能的縮短版本:

client = new StreamClient();
client.Connect(new IPEndPoint(clientAddress, senderPort));
stream = client.GetStream();
bool status = SendMessage(seq, sync, MessageTypes.Init);

SendMessage函數執行:

if (stream == null) return false;
stream.Write(TransmitBuffer, 0, TransmitMessageLength);

我的關閉功能:

if (stream != null)
{
    SendMessage(seq, sync, MessageTypes.Finish);
    stream.Close();
}
stream = null;

client.Close();
client = null;

由於套接字的性質,預計SendMessage調用偶爾會失敗。

但有時候,一旦我連接,一切運行正常,沒有失敗的消息。 但有時候ACK會失敗。 當ACK失敗時,我調用Close,這將強制連接並驗證套接字的另一端是否打開。 如果失敗那么我知道結束了。 但有時候這個呼叫不會失敗,然后20秒后ACK就會失敗。

誰能給我一個關於為什么會發生這種情況的意見? 等待20秒太長了嗎? 我沒有正確關閉插座的末端嗎?

我正在與之爭斗的具體錯誤信息是:

Unable to write data to the transport connection: An established connection was aborted by the software in your host machine.

它發生在stream.Write(TransmitBuffer, 0, TransmitMessageLength);

通常,將協議置於TCP之上是一個很大的錯誤。 它只能使連接不太可靠。 TCP已經非常有力地保證從一台機器發送的數據將由網絡上的另一台機器接收。 只有非常嚴重的外部環境才能使失敗。 設備斷電或計划外重啟等事情。

一個連接應該被打破,除非機器的人故意關閉套接字。 當然,這應該以可預測的方式進行。 事務的邏輯結束或計算機正在注銷的顯式消息。

除了“保持流關閉”之外,您沒有給出任何將“ACK協議”添加到連接邏輯的動機。 我認為你在這里看到的是它只是不起作用,它實際上並沒有阻止流關閉。 因此,在添加協議層之前,它仍然會出現問題,您仍然會遇到意外的“已建立的連接已中止”異常。

您添加的20秒超時檢查是一個如何使其不太可靠的示例。 TCP不使用20秒超時。 它使用指數退避算法來檢查超時。 通常它至少在45秒后才會放棄。 因此, TCP執行此操作之前,您將聲明連接已死。

很難就如何向前推進提出建議。 但顯然不是通過添加協議,你嘗試了它並且它不起作用。 您必須找出連接意外斷開的原因。 不幸的是,這確實需要合作,您必須深入了解機器和服務器之間的網絡設備和軟件。 有些人期望問題位於電線的另一端,因為那是最難診斷的問題。 讓網站的網絡管理員參與您的問題是重要的第一步。

我在你的實現中看到的主要內容是,我看起來你將Stream視為連接,而事實並非如此。 您對Stream實例的檢查應該是對TcpClient實例的檢查。 我不確定這是否是你問題的根源,但它對我來說肯定很奇怪。

而不是這個:

stream = client.GetStream();
if (stream != null)
{
    SendMessage(seq, sync, MessageTypes.Finish);
    stream.Close();
}
stream = null;

我通常會做更像這樣的事情:

if (client != null)
{
    if (client.Connected)
    {
        client.GetStream().Close();
    }

    client.Close();
    client = null;
}

您應該在使用流之前檢查TcpClient.Connected,而不是流本身。
我要提到的另一件事是確保始終使用異步方法與TcpClient連接,讀取和寫入。 同步的更容易,但我的經驗是依靠它們會讓你陷入困境。

在開發網絡通信庫時我們遇到了類似的問題。 我們發現最可靠的解決方案只是發送一些空數據(即保持活躍),而不是使用ACK。 在這種情況下,字節[1]的值為零。 這將導致:

  1. 成功的發送和數據可以在接收端被忽略。
  2. 發送失敗,會立即導致連接關閉並重新建立。

這些結果中的任何一個都確保了連接始終處於可用狀態。

你為什么發送ACK? 你應該發送SYN。

並且您不應該發送ACK,SYN,RST或設置任何其他標志。 你正在涉足TCP內部。 你正在創建應用程序級協議,keep-alive是其中的一部分,因為,即使有http://msdn.microsoft.com/en-us/library/windows/desktop/ee470551%28v=vs.85 %29.aspx連接將一直打開,直到您關閉它。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM