2010-08-20 73 views
1

我有這個很好的ASYNC tcp流類,我用它來連接perl tcp服務器,然後每次發送msg給它。也許從30個字節到200-500個字節通常不會很長。 95%,但它工作正常,但我有一個問題,它經常發送消息中斷(通過一些字符),然後發送其餘的消息,這有點分手了。任何人都可以建議如何解決這個問題?我試圖改變一些東西,但沒有真正能夠解決它。截斷消息的異步網絡流問題c#

public class TcpStream { 
    private readonly NetworkStream _stream; 
    public event EventHandler<TcpDataEventArgs> DataReceived; 
    public event EventHandler<TcpErrorEventArgs> ErrorOccurred; 
    public TcpStream(NetworkStream stream) { 
     this._stream = stream; 
    } 
    public void BeginRead() { 
     var state = new SocketState {Stream = _stream}; 
     //var bytes = new byte[1024]; 

     //IAsyncResult ar = _stream.BeginRead(state.Data, 0, state.Data.Length, HandleRead, state); 
     IAsyncResult ar = _stream.BeginRead(state.Data, 0, state.Data.Length, HandleRead, state); 


    } 
    public void Send(byte[] data, ProtocolConnection protocolConnection) { 
     //try { 
     _stream.Write(data, 0, data.Length); 
     //} catch (Exception ex) { 
     //  OnError(new TcpErrorEventArgs(ex, stream, protocolConnection)); 
     // } 
    } 
    public void Send(String data, ProtocolConnection protocolConnection) { 
     byte[] d = Encoding.Default.GetBytes(data); 
     Send(d, protocolConnection); 
    } 
    public void Close() { 
     _stream.Close(); 
    } 
    public void Close(int timeout) { 
     _stream.Close(timeout); 
    } 

    public NetworkStream BaseStream { 
     get { return _stream; } 
    } 

    private void HandleRead(IAsyncResult ar) { 
     var state = (SocketState) ar.AsyncState; 
     NetworkStream stream = state.Stream; 
     int r; 
     // check to see if stream has been closed 
     if (!stream.CanRead) 
      return; 
     // try { 
     r = stream.EndRead(ar); 
     // } catch (Exception ex) { 
     //  OnError(new TcpErrorEventArgs(ex, stream, _protocolConnection)); 
     //  return; 
     // } 
     var rdata = new byte[r]; 
     //var rdata = new byte[1024]; 
     Buffer.BlockCopy(state.Data, 0, rdata, 0, r); 
     OnData(new TcpDataEventArgs(rdata)); 
     // try { 
     BeginRead(); 
     // } catch (Exception ex) { 
     //  OnError(new TcpErrorEventArgs(ex, stream, _protocolConnection)); 
     // } 
    } 
    private void OnData(TcpDataEventArgs args) { 
     EventHandler<TcpDataEventArgs> temp = DataReceived; 
     if (temp != null) 
      temp(this, args); 
    } 
    private void OnError(TcpErrorEventArgs args) { 
     EventHandler<TcpErrorEventArgs> temp = ErrorOccurred; 
     if (temp != null) 
      temp(this, args); 
    } 

    private class SocketState { 
     public readonly byte[] Data = new byte[100]; 
     public NetworkStream Stream; 
    } 

    public class TcpDataEventArgs : EventArgs { 
     public readonly byte[] Data; 
     public TcpDataEventArgs(byte[] data) { 
      this.Data = data; 
     } 
    } 

    public class TcpErrorEventArgs : EventArgs { 
     public readonly Exception Error; 
     private NetworkStream Stream; 
     public TcpErrorEventArgs(Exception error, NetworkStream stream) { 
      this.Error = error; 
      this.Stream = stream; 
     } 
    } 
} 
+4

感嘆。 <插入通用答案,解釋TCP不是面向消息的傳輸。推薦使用其他方式來分隔消息> – dtb 2010-08-20 20:44:11

+0

您最終需要從套接字讀取數據,直到達到分隔符或指定數量的字符。希望PERL服務器有一些使用其中一種的方法。 – 2010-08-20 21:01:35

+0

@Mike它發送消息,然後\ n – MadBoy 2010-08-21 08:43:19

回答

3

TCP是一種字節流協議。傳輸的數據包和你的'消息'之間沒有直接的關係。您需要閱讀字節並查找消息。

一個非常簡單的例子:如果消息是行(以LF或CRLF結尾的字符串),則可以將StreamReader附加到NetworkStream並使用ReadLine。不要低估這樣做的便利,UTF-8編碼的字符可以分成2個數據包。