【问题标题】:NetworkStream.Read doesn't work the first time calledNetworkStream.Read 在第一次调用时不起作用
【发布时间】:2011-06-01 13:25:39
【问题描述】:

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

 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
            {

            }
        }

【问题讨论】:

  • 关于 TCP 的一件重要的事情是它以流的形式而不是以数据包的形式传递数据。一个 Write 调用可能会分段到达,多个 write 调用可能一起到达。

标签: c# .net tcp ip


【解决方案1】:

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

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

【讨论】:

    【解决方案2】:

    我不确定它是否与问题直接相关,但您使用的Read 方法错误。您正在将数据读入缓冲区,但您忽略了实际读取了多少数据,假设 Read 调用始终返回您请求的数据,因此您正在解码整个缓冲区,即使它可能没有完全填充。

    获取Read 调用的返回值,以便了解实际填充了多少缓冲区的数据:

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

    【讨论】:

      【解决方案3】:

      您需要实现 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();
      }
      }
      

      【讨论】:

      • 我永远无法到达“其他”。当我到达 s.BeginReceive 时,如果所有数据都已被处理,它不会调用 Read_Callback,直到发送另一条消息。有没有办法知道每个发送的数据包是如何读取所有数据的?
      猜你喜欢
      • 1970-01-01
      • 2012-10-16
      • 1970-01-01
      • 1970-01-01
      • 2013-04-27
      • 2011-12-14
      • 2018-06-15
      • 2016-03-30
      • 2021-08-26
      相关资源
      最近更新 更多