如何在NetworkStream字节数组中放置分隔符?

7

我正在构建一个服务器和客户端之间通信的方式。目前的工作方式是,数据流的第一个字节包含要传递的内容指示器,然后查找该请求的类别,以确定请求的长度:

stream.Read(message, 0, 1)

if(message == <byte representation of a known class>)
{
    stream.Read(message, 0, Class.RequestSize);
}

我想知道如何处理班级规模未知的情况,或者在读取已知请求后数据损坏的情况下应该怎么办。

我考虑可以在流中插入某种分隔符,但由于字节只能介于0-255之间,我不确定如何创建一个独特的分隔符。我想在流中放置一个模式来表示消息的结束吗?我如何确保这个模式足够独特,不会被误认为是实际数据?


1
将您的流分成固定大小的块(例如64K)。在每个块前加上当前大小的2个字节,当您接收到一个大小不为0xFFFF的块时,表示已到达流的末尾。不要试图拥有唯一的模式,除非您对输入数据进行编码(但这会使它们变得更大),否则肯定会出现问题。 - Adriano Repetti
@Adriano,按照您的方法,我该如何防止有人一直发送0xFFFF大小的数据? - afuzzyllama
如果发送者是恶意的,除非您设置一个任意限制,否则您无法做到这一点。但是,如果您可以在第一个块之前接收到额外的计数器(指将要发送的块数),则可以限制最大大小。然而,我会考虑两次是否添加此类数据完整性检查。这种东西在协议的较低级别上处理(您是否使用TCP连接?)。 - Adriano Repetti
我目前正在使用TcpClient类。我只是试图弄清楚如何清除错误的流并尝试获取下一个流。 - afuzzyllama
2个回答

4

有不同的方法来解决这个问题。一种选择是首先发送类名的长度和整个数据包的长度(例如,始终是第一个字节)。这样你只需要读取那个字节,然后再读取n个字节以获取类名。

通过这种方法,你可以避免读取恶意客户端发送给你的大量信息,从而防止应用程序被DoS攻击,并且可以快速确定是否已经读取足够的信息来处理数据包,以及它是否已经完整。


0

有一些低级字节被用作分隔符,特别是文本开始和文本结束,它们的十六进制值分别为0x02和0x03。此外,你还可以使用标题开始和传输结束,它们的值分别为0x01和0x04。


3
只有在确保数据永远不包含那些字符的情况下,才可以这样做。如果他正在处理的是非文本格式的二进制数据,则情况则不同。 - ThiefMaster
当然,但这取决于他的数据,我认为至少提一下这个是可以的。 - Davio

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接