代码之家  ›  专栏  ›  技术社区  ›  MadBoy

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

  •  1
  • MadBoy  · 技术社区  · 15 年前

    我有一个很好的异步TCP流类,我用它连接到PerlTCP服务器,然后每隔一段时间就会向它发送消息。它通常不会很长,从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 回复  |  直到 15 年前
        1
  •  3
  •   Henk Holterman    15 年前

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

    一个非常简单的例子:如果消息是行(以lf或crlf结尾的字符串),那么可以将streamreader附加到网络流并使用readline。不要低估这样做的便利性,一个UTF-8编码字符可以被拆分为两个数据包。

    推荐文章