切断消息的异步网络流问题c#

时间:2010-08-20 20:41:49

标签: c# networking

我有一个很好的ASYNC tcp流类,我用它连接到perl tcp服务器,然后每隔一段时间就向它发送一个msg。它通常不会很长,从30个字符到200-500个。 95%它工作正常,但我有一个问题,它经常发送消息切断(由一些字符),然后发送其余的消息,这有点打破了事情。有谁能建议如何克服这个问题?我试图改变一些事情,但实际上无法修复它。

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;
        }
    }
}

1 个答案:

答案 0 :(得分:3)

TCP是一种字节流协议。传输的数据包与您的“消息”之间没有直接关系。由您来读取字节并查找消息。

一个非常简单的示例:如果消息是行(以LF或CRLF结尾的字符串),您可以将StreamReader附加到Networkstream并使用ReadLine。不要低估这样做的便利性,UTF-8编码的字符可以分成2个数据包。