繁体   English   中英

NetworkStream.Read在第一次调用时不起作用

[英]NetworkStream.Read doesn't work the first time called

我有一个带有服务器和客户端的简单tcp / ip聊天程序。 我第一次发送数据包时,它将它发送给客户端,但是在NetworkStream期间读取它会停止执行并且不会引发异常。 我发送的下一个数据包被完美读取和处理。 我注意到的另一个奇怪的事情是,即使我从服务器获取信息,MyNetworkStream.DataAvailable始终为false,因此我必须放置调试符号并跳过它。 我希望可以发布所有代码,但是很长,因此我会将发布的地方写入网络流中。

 public void Listen(int byteLength)
        {
            var buffer = new byte[byteLength];
            MySocket.BeginReceive(buffer, 0, buffer.Length, SocketFlags.None, new AsyncCallback(Read), buffer);
        }

        private  void Read(IAsyncResult ar)
        {
            while (MySocket.Connected)
            {
            MyNetworkStream = new NetworkStream(MySocket);
            var buffer = new byte[((byte[])ar.AsyncState).Length];
            if (!MyNetworkStream.DataAvailable)
                throw new Exception("Data not available");
                MyNetworkStream.Read(buffer, 0, buffer.Length); <------Here it stops execution without throwing an exception
                string content = Encoding.ASCII.GetString(buffer);
                if(OnRead == null)
                    continue;
                var e = new CommandEventArgs( null, content);
                Control target = null;
                if (OnRead.Target is Control)
                    target = (Control)OnRead.Target;
                if (target != null && target.InvokeRequired)
                    target.Invoke(OnRead, this, e);
                else
                    OnRead(this,e);

            }
        }


        public void Write(string message)
        {
            try
            { 
                var buffer = Encoding.ASCII.GetBytes(message);
                MySocket.BeginSend(buffer, 0, buffer.Length, SocketFlags.None, null, null);
                if (OnWrite != null)
                {
                    var target = (Control)OnWrite.Target;
                    if (target != null && target.InvokeRequired)
                    {
                        target.Invoke(OnWrite, this, new EventArgs());
                    }
                    else
                    {
                        OnWrite(this, new EventArgs());
                    }
                }
            }
            catch
            {

            }
        }

BeginReceive异步等待消息并填充缓冲区。 然后,您开始从套接字同步读取,覆盖过程中的第一条消息。

您应该调用EndReceive ,它返回读取的字节数,然后在尝试读取更多字节之前处理缓冲区。

我不确定这是否与问题直接相关,但是您使用的Read方法错误。 您正在将数据读取到缓冲区中,但是假设Read调用始终返回所需的数据量,则您实际上忽略了实际读取的数据量,因此即使可能没有完全填充缓冲区,也要解码整个缓冲区。

获取Read调用的返回值,以便您知道实际上有多少缓冲区已被数据填充:

int len = MyNetworkStream.Read(buffer, 0, buffer.Length);
string content = Encoding.ASCII.GetString(buffer, 0, len);

您需要实现EndRecieve才能从流中获取完整的数据。 从MSDN签出以下示例:

public static void Read_Callback(IAsyncResult ar){
    StateObject so = (StateObject) ar.AsyncState;
    Socket s = so.workSocket;

int read = s.EndReceive(ar);

if (read > 0) {
        so.sb.Append(Encoding.ASCII.GetString(so.buffer, 0, read));
        s.BeginReceive(so.buffer, 0, StateObject.BUFFER_SIZE, 0, 
                                 new AsyncCallback(Async_Send_Receive.Read_Callback), so);
}
else{
     if (so.sb.Length > 1) {
          //All of the data has been read, so displays it to the console
          string strContent;
          strContent = so.sb.ToString();
          Console.WriteLine(String.Format("Read {0} byte from socket" + 
                           "data = {1} ", strContent.Length, strContent));
     }
     s.Close();
}
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM