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

时间:2010-12-30 13:03:59

标签: c# .net tcp ip

我有一个简单的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
            {

            }
        }

3 个答案:

答案 0 :(得分:2)

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

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

答案 1 :(得分:1)

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

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

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

答案 2 :(得分:0)

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