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

发布于 2024-10-09 10:12:52 字数 2242 浏览 0 评论 0原文

我有一个带有服务器和客户端的简单 tcp/ip 聊天程序。我第一次发送数据包时,它会将其发送到客户端,但在 NetworkStream.Read 期间,它会停止执行并且不会引发异常。我发送的下一个数据包将被完美读取和处理。我注意到的另一个奇怪的事情是,即使我从服务器获取信息,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
            {

            }
        }

I have a simple tcp/ip chat program with a server and client. The first time I send a packet, it makes it to the client but during the NetworkStream.Read it stops execution and doesn't throw an exception. The next packet I send is read and processed perfectly. Another weird thing I noticed is that MyNetworkStream.DataAvailable is always false even if I get information from the server so I have to put a debug symbol and skip over it. I wish I could post all my code but it is long so I will post where I read and write to the network stream.

 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
            {

            }
        }

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

皇甫轩 2024-10-16 10:12:52

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

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

BeginReceive asynchronously waits for a message and fills your buffer. You then start synchronously reading from the socket, overwriting the first message in the process.

You should call EndReceive which returns the number of bytes read, then process your buffer before trying to read more bytes.

从﹋此江山别 2024-10-16 10:12:52

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

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

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

I'm not sure if it's directly related to the problem, but you are using the Read method wrong. You are reading data into the buffer, but you are ignoring how much data was actually read assuming that the Read call always returns as much data as you request, so you are decoding the entire buffer eventhough it might not be completely filled.

Get the return value of the Read call so that you know how much of the buffer is actually filled with data:

int len = MyNetworkStream.Read(buffer, 0, buffer.Length);
string content = Encoding.ASCII.GetString(buffer, 0, len);
别想她 2024-10-16 10:12:52

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

You need to implement EndRecieve to get the complete data from the stream. Checkout the following example from 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();
}
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文