来自NetworkStream的Write()和Read()原始字节,某些字节的数据存在差异 [英] Write() and Read() raw bytes from NetworkStream, data is difference at some bytes

查看:184
本文介绍了来自NetworkStream的Write()和Read()原始字节,某些字节的数据存在差异的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经写了一些代码,用于在发送之前使用大小为KNOWN的NetworkStream发送byte []数组,但是发送的数据和接收的数据在某些位置有所不同.

I've written some code for sending byte[] array using NetworkStream with KNOWN size before sending, but the data sent and data received are difference at some positions.

MAXSIZE是我要发送的数据的已知大小.

MAXSIZE is the known size of the data I want to send.

    public static void SendBytes(TcpClient clientSocket, byte[] outStream)
    {
        Debug.WriteLine("SendBytes() number of bytes: " + outStream.Length.ToString());

        NetworkStream serverStream = clientSocket.GetStream();

        serverStream.Write(outStream, 0, outStream.Length);
        //serverStream.Flush();
    }

    public static byte[] ReceiveBytes(TcpClient clientSocket, int MAX_SIZE)
    {
        Debug.WriteLine("[" + DateTime.Now.ToString("G") + "] - " + "ReceiveBytes() started.");

        NetworkStream networkStream = clientSocket.GetStream();

        byte[] bytesFrom = new byte[MAX_SIZE];
        clientSocket.ReceiveBufferSize = MAX_SIZE;

        networkStream.Read(bytesFrom, 0, (int)clientSocket.ReceiveBufferSize);

        Debug.WriteLine("[" + DateTime.Now.ToString("G") + "] - " + "ReceiveBytes(), received number of raw bytes: " + bytesFrom.Length.ToString());

        return CommonUtils.SubArray(bytesFrom, 0, MAX_SIZE);
    }

如果发送数据(十六进制字节):a7 fc d0 51 0e 99 cf 0d 00,接收到的数据为:a7 fc d0 51 0e 99 cf 0d 53

If sending the data (bytes in hex): a7 fc d0 51 0e 99 cf 0d 00 , the received data is : a7 fc d0 51 0e 99 cf 0d 53

推荐答案

由于数据包的结构化,很可能您会看到垃圾;TCP仅保证正确的字节将以正确的顺序到达(否则流将失败)-它没有提及它们到达的.因此,您重要:

Most likely you're seeing garbage due to packet structuring; TCP only guarantees that the correct bytes will arrive in the correct order (or a stream failure) - it says nothing about the chunks in which they arrive. Because of that, it is vital that you:

  1. Read 捕获返回值,并且仅处理来自任何块的这么多字节
  2. 执行您自己的取景-即将流分批发送到消息中,而与消息的到达方式无关
  1. catch the return value from Read, and only process that many bytes from any chunk
  2. perform your own framing - i.e. batching the stream into messages independent of how the pieces arrive

如果您的消息始终固定大小,则"2"将变为缓冲数据,直到我至少有N个字节,然后以N块的形式处理数据,保留剩下的所有内容,然后恢复缓冲".但是在一般情况下,它可能是缓冲,直到我看到一个前哨值,例如换行",或者是缓冲,直到我有一个完整的标头,然后解析标头以查看期望的数据量,然后缓冲直到我有那么多数据".

If your messages are always fixes size, then "2" becomes "buffer data until I have at least N bytes, then process the data in chunks of N, retaining whatever is left over, then resume buffering". But in the general case, it might be "buffer until I see a sentinel value, such as a line-feed", or "buffer until I have a complete header, then parse the header to see how much data to expect, then buffer until I have that much data".

有一些工具和实用程序可帮助简化帧删除和处理积压工作-例如,使用新的管道" API,这只是检查管道并告诉管道您要消耗多少的一种情况(而不是为您提供一切,并且您暂时无法拒绝数据)-但是对于大多数人来说,从 Stream 切换到管道"是相当多的变化.

There are tools and utilities to help make de-framing and handling backlog much simpler - for example, with the new "pipelines" API it is simply a case of inspecting the pipe and telling the pipe how much you want to consume (rather than it giving you everything and you having no way of rejecting data for now) - but switching from Stream to "pipelines" is quite a bit set of changes for most people.

就您而言,您可能可以使用:

In your case, you can probably use:

byte[] bytesFrom = new byte[MAX_SIZE];
int outstanding = MAX_SIZE, read, offset = 0;
while (outstanding > 0 && (read = networkStream.Read(bytesFrom, offset, outstanding)) > 0)
{
    offset += read;
    outstanding -= read;
}
if (outstanding != 0) throw new EndOfStreamException();

这将创建一个读取循环,该读取循环会完全填充 bytesFrom ,否则会因异常而失败.

This creates a read loop that fills bytesFrom completely, or fails with an exception.

这篇关于来自NetworkStream的Write()和Read()原始字节,某些字节的数据存在差异的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆