2010-04-04 43 views
2

我有一個線程是通過套接字這樣接收數據:.NET套接字緩衝區溢出沒有錯誤

while (sock.Connected) 
{ 
    // Receive Data (Block if no data) 
    recvn = sock.Receive(recvb, 0, rlen, SocketFlags.None, out serr); 

    if (recvn <= 0 || sock == null || !sock.Connected) 
    { 
     OnError("Error In Receive, recvn <= 0 || sock == null || !sock.Connected"); 
     return; 
    } 
    else if (serr != SocketError.Success) 
    { 
     OnError("Error In Receive, serr = " + serr); 
     return; 
    } 

    // Copy Data Into Tokenizer 
    tknz.Read(recvb, recvn); 

    // Parse Data 
    while (tknz.MoveToNext()) 
    { 
     try 
     { 
      ParseMessageAndRaiseEvents(tknz.Buffer(), tknz.Length); 
     } 
     catch (System.Exception ex) 
     { 
      string BadMessage = ByteArrayToStringClean(tknz.Buffer(), tknz.Length); 
      string msg = string.Format("Exception in MDWrapper Parsing Message, 
          Ex = {0}, Msg = {1}", ex.Message, BadMessage); 
      OnError(msg); 
     } 
    } 
} 

我總是看到在我的分析功能偶然的錯誤指示該消息是無效的。起初,我認爲我的tokenizer類被破壞了。但是,在將所有傳入字節記錄到標記器後,事實證明recvb中的原始字節不是有效的消息。我不認爲這樣的數據流是可以通過tcp數據流破壞的。

我想它必須是某種類型的緩衝區溢出,所以我設置

sock.ReceiveBufferSize = 1024 * 1024 * 8; 

,從不解析錯誤,曾經發生在測試(它發生的頻率足以複製,如果我不改變ReceiveBufferSize )。

但我的問題是:爲什麼我沒有看到一個異常或錯誤狀態,或者如果在更改此緩衝區大小之前套接字的內部緩衝區溢出了?

回答

2

我還建議確認數據的發送者正在檢查成功寫入的字節數,而不是假定所有字節都已成功寫入。

這是使用Socket.Send時常見的錯誤,也可以解釋爲什麼當您調整緩衝區大小時,問題會消失。

發件人有責任重試,直到所有字節都成功寫入。

+0

感謝您的回覆。這是一個很好的觀點,它可能在發件人一方。這將解釋爲什麼套接字不報告任何錯誤。如果字節正確傳遞,但發件人有一些問題,而不是全部發送給我,因爲緩衝區已滿,那可能就是這樣。我想我應該用wireshark捕獲服務器發送的數據包來確認。 – 2010-04-05 02:19:25

+0

我想你的權利,設法讓服務器的人今天和他的日誌文件記錄輸出:「發送():短送98,應該是106.」 所以看起來他沒有發送所有東西,因爲我的接收緩衝區已滿。謝謝你的幫助! – 2010-04-05 19:01:37

4

我假設你的標記器需要文本(Utf8?),但是(套接字)流使用字節數據。多字節字符在傳輸中可能會分裂。一個小緩衝區增加了發生這種情況的可能性。

如果您使用的ASCII碼是安全的,否則解決方案將使用TextReader作爲中間件。

+0

感謝您的回覆。我沒有想過這個。幸運的是,這是使用ASCII。我收到的數據的數據包結構具有ascii字符31(單位分隔符)作爲消息之間的分隔符。只是從recvb捕獲原始數據並寫入文件表明這些消息是無效的(至少兩個消息在它們之間沒有字符31的情況下重疊時,數組中的一個點)。 – 2010-04-04 23:26:43

+0

@邁克爾,好的,但仍然檢查你的標記器的邏輯。從你的代碼中,標記器負責重新組裝消息。也就是說,在嘗試查找下一條消息之前,必須記住任何不完整的消息並追加新的數據。 – 2010-04-04 23:31:20

+0

標記器不會重新組裝消息。肯定可能會有一個錯誤。但我不認爲這是我在這裏看到的問題。我在記錄recvn內容到達記號器之前先進行記錄。只要將這些字節寫入到文件中,並且其中的消息不正確(即兩個消息存在重疊,不會被ascii令牌31分隔)。 – 2010-04-04 23:54:24