Проблема асинхронного сетевого потока с обрезкой сообщений c # - PullRequest
1 голос
/ 21 августа 2010

У меня есть замечательный потоковый класс ASYNC tcp, который я использую для подключения к серверу perl tcp, который затем время от времени отправляет ему сообщения. Обычно это не очень долго от 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 Ответ

3 голосов
/ 21 августа 2010

TCP - это протокол потока байтов. Нет прямой связи между передаваемыми пакетами и вашими «сообщениями». Это зависит от вас, чтобы прочитать байты и найти сообщения.

Очень простой пример: если сообщения представляют собой строки (строки, оканчивающиеся на LF или CRLF), вы можете присоединить StreamReader к Networkstream и использовать ReadLine. Не стоит недооценивать удобство этого, кодированный символ UTF-8 может быть разделен на 2 пакета.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...