【问题标题】:Strange behaviour of networkstream.read() in C#C# 中 networkstream.read() 的奇怪行为
【发布时间】:2009-09-04 01:35:04
【问题描述】:

当我向网络流写入两个单独的字节数组时,有时我没有得到第一个字节数组。 这是为什么呢?

例如,这失败了,没有收到标头,有时是另一端的 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);

            }

【问题讨论】:

    标签: c# tcp network-programming


    【解决方案1】:

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

    【讨论】:

    • 但这不是违反tcp ip协议,应该不会有数据丢失,它是一个可靠的面向连接的协议
    • 我不知道该告诉你什么。我只是在前天不得不处理这个问题。而且...这不是第一次 API 不符合特定规范。
    • 而且...总是有可能有一个空缓冲区。无论您期待多少 mch 数据,您总是需要考虑一个空缓冲区。这就是为什么在尝试读取之前有一个 DataAvailable 属性供您查询。
    【解决方案2】:

    您可以通过注释掉第二个 Write 来解决它,看看您的服务器是否发送了任何数据。

    您的阅读机制看起来确实非常脆弱,我同意 Simon Fox 的观点,即它看起来并不正确。为什么第二次读取要求 len + 5 个字节?我原以为它只会是 len 个字节,因为第一次读取是针对 4 个标头字节的。

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

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

    【讨论】:

      【解决方案3】:

      你不是在第二次调用中覆盖你在第一次调用中读取的内容吗? Read 的第二个参数是开始存储读取数据的偏移量,两个调用都使用 0,因此第二个参数覆盖第一个...

      【讨论】:

      • 不,我在第一次调用中读取的内容通过将其转换为整数将其存储在 len 中,然后我在同一位置读取,但我第一次调用 read 并没有读取第一组我发送的字节数
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-08-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多