2010-08-24 62 views
1
var buffer = new byte[short.MaxValue]; 
var splitString = new string[] {"\r\n"}; 
while (_tcpClient.Connected) 
{ 
    if (!_networkStream.CanRead || !_networkStream.DataAvailable) 
    continue; 

    var bytesRead = _networkStream.Read(buffer, 0, buffer.Length); 
    var stringBuffer = Encoding.ASCII.GetString(buffer, 0, bytesRead); 
    var messages = 
    stringBuffer.Split(splitString, StringSplitOptions.RemoveEmptyEntries); 
    foreach (var message in messages) 
    { 
    if (MessageReceived != null) 
    { 
     MessageReceived(this, new SimpleTextClientEventArgs(message)); 
    } 
    } 
} 

問題是,即使使用與short.MaxValue一樣大的緩衝區,您實際上可以填充緩衝區。當你將你創建的字符串從緩衝區中分離出來時,最後一個字符串會被刪除,其餘的字符會隨着下一次讀取而來。使用NetworkStream的IRC - 緩衝區填充和行被取消

我正在考慮爲單行創建一個足夠大的緩衝區(根據RFC2812是512個字符),提取子字符串直到第一個「\ r \ n」,然後數組複製剩餘的數據到緩衝區的開始,並使用偏移參數將更多數據讀取到最後一次迭代未提取的數據末尾。對不起,如果很難遵循...

這是最好的解決方案,還是我錯過了這裏明顯?

+0

你確定緩衝區滿,不就是'bytesRead'不與發送的字節數相同的大小? – 2010-08-24 07:51:26

+0

可能是這種情況 - 但通常情況並非如此。 – carlsb3rg 2010-08-24 08:05:39

回答

0

因此,這裏是我是如何結束的解決它:

var buffer = new byte[Resources.MaxBufferSize]; 
var contentLength = 0; 
while (_tcpClient.Connected) 
{ 
    if (!_networkStream.CanRead || !_networkStream.DataAvailable) 
    continue; 

    var bytesRead = _networkStream.Read(buffer, contentLength, buffer.Length - contentLength - 1); 
    contentLength += bytesRead; 
    var message = string.Empty; 
    do 
    { 
    message = ExtractMessage(ref buffer, ref contentLength); 
    if (!String.IsNullOrEmpty(message)) 
    { 
     if (MessageReceived != null) 
     { 
     MessageReceived(this, new SimpleTextClientEventArgs(message)); 
     }       
    } 
    } while (message != string.Empty); 
} 

private string ExtractMessage(ref byte[] buffer, ref int length) 
{ 
    var message = string.Empty; 
    var stringBuffer = Encoding.UTF8.GetString(buffer, 0, length); 
    var lineBreakPosition = stringBuffer.IndexOf(Resources.LineBreak); 
    if (lineBreakPosition > -1) 
    { 
    message = stringBuffer.Substring(0, lineBreakPosition); 
    var tempBuffer = new byte[Resources.MaxBufferSize]; 
    length = length - message.Length - Resources.LineBreak.Length; 
    if (length > 0) 
    { 
     Array.Copy(buffer, lineBreakPosition + Resources.LineBreak.Length, tempBuffer, 0, length); 
     buffer = tempBuffer; 
    } 
    } 
    return message; 
} 
1

你正在處理TCP/IP,這意味着你正在處理數據。您必須而不是依賴於數據是如何通過一個呼叫Read是否會給您全部數據。在這樣的情況下,你可能想繼續閱讀(它會阻塞,直到有一些數據),並找到將二進制數據轉換爲文本緩衝區。當你在文本緩衝區中看到一個行結束符時,你可以通知該消息的更高級別,並將其從緩衝區中移除......但不要假設在該消息之後會發生什麼。您可能仍然有更多的數據可供閱讀。

作爲一個側面說明,是IRC 真的只有 ASCII?如果是這樣,至少使事情變得簡單一點......

+0

- 這就是它說的: - 「沒有指定特定的字符集,該協議是基於一組由八(8)位組成的代碼組成的,每個消息可以由任意數字這些八位字節;但是,一些八位字節值用於控制代碼,它們充當消息分隔符。「 但是我知道IRC協議中有沒有記錄在文件中/沒有明確記錄的增強功能,所以我想盡可能使功能更強大。我認爲你的建議就是我在我的最後一段 – carlsb3rg 2010-08-24 08:06:59

+0

@ carlsb3rg中建議的內容:是的,這聽起來像你可能會和我一樣思考。這聽起來像協議完全破壞,如果它沒有指定一個編碼,但通過假設ASCII你可能很容易失去重要的數據。特別是,聽起來你應該通過字節數組來查看消息分隔符而不是解碼文本。 – 2010-08-24 08:29:51

相關問題