C#中networkstream.read()的奇怪行为

时间:2009-09-04 01:35:05

标签: c# tcp network-programming

当我写一个网络流两个单独的字节数组时,我有时候得不到第一个字节数组。 那是为什么?

例如,如果失败,则不会收到标题,有时是另一方的Read()

            byte[] header = msg.getByteHeader();
            byte[] data = msg.getByteData();
            clientStream.Write(header, 0, header.Length);
            clientStream.Write(data, 0, data.Length);
            clientStream.Flush();

然而这成功了

                NetworkStream clientStream = tcpClient.GetStream();
                byte[] header = msg.getByteHeader();
                byte[] data = msg.getByteData();
                int pos = 0;
                Array.Copy(header, 0, message, pos, header.Length);
                pos += header.Length;
                Array.Copy(data, 0, message, pos, data.Length);
                clientStream.Write(message, 0, message.Length);

这就是我的Read()外观

           try
            {
                //blocks until a client sends a message
                bytesRead = clientStream.Read(message, 0, 4);
                //string stringData = Encoding.ASCII.GetString(message, 0, bytesRead);
                len = BitConverter.ToInt32(message, 0);
                //MessageBox.Show(len.ToString());
                bytesRead = clientStream.Read(message, 0, 5 + len);

            }

3 个答案:

答案 0 :(得分:1)

我认为这是一个时间问题。首次打开套接字通信和从缓冲区读取第一个数据之间存在延迟。这不是瞬间的。您可以在尝试读取之前查询网络流的DataAvailable布尔状态。如果没有DataAvailable,请将线程称为100毫秒,然后再次尝试读取。

答案 1 :(得分:1)

您可以通过注释掉第二次写入来查看它,然后查看您的服务器是否发送了任何数据。

你的阅读机制看起来非常脆弱,我同意西蒙福克斯认为这看起来不正确。为什么第二次读取要求len + 5字节?我原以为它只是len字节,因为第一次读取是4个字节字节。

如果我是你,我会在标题传输的开头添加一个分隔符。这将允许您的接收器扫描它以确定数据包的开始。使用TCP,您通常会将捆绑的传输或多个传输捆绑到同一个数据包中。如果您总是依赖于获取所请求的字节数,那么一旦部署到互联网等真实网络,事情就会出错。

或者切换到UDP,你可以依赖每个数据包进行一次传输。

答案 2 :(得分:0)

你是不是在第二次通话的第一次通话中覆盖了你所读到的内容? Read的第二个参数是开始存储数据读取的偏移量,两个调用都使用0,所以第二个会覆盖第一个...