这是我的分支 另一个问题. 。如果愿意,请阅读,但这不是必需的。

基本上,我意识到,要在大消息上有效地使用C#的beginReceive(),我需要(a)先读取数据包长度,然后读取完全多字节或(b)使用“末端”分界符。我的问题是,这些都存在于协议缓冲区中吗?我尚未使用它们,但是浏览文档似乎没有一个长的标题或定界符。

如果没有,我该怎么办?我应该只是构建消息,然后用长度标头/EOP定界符前缀/后缀?

有帮助吗?

解决方案

您需要在协议中包含大小或终端标记。除了支撑无限期的八位位集之外,基于流的插座(TCP/IP)没有任何内置的内置。

一个简单的方法是每个“消息”具有固定尺寸标头,包括协议版本和有效负载大小以及任何其他固定数据。然后消息内容(有效负载)。

可选的是,可以使用校验和什至加密签名(根据您的可靠性/安全要求)添加消息页脚(固定尺寸)。

了解有效载荷尺寸使您可以继续读取许多字节,这些字节足以容纳消息的其余部分(如果读取完成了较少的读数,则对剩余字节进行另一项读取,直到收到整个消息为止)。

拥有终端消息指示器也可以工作,但是您需要定义如何处理包含相同八位位序列的消息...

其他提示

为参加聚会迟到而道歉。我是Protobuf-net的作者,这是C#实施之一。对于网络使用情况,您应该考虑“ [de] serializeWithLengthPrefix”方法 - 这样,它将自动处理您的长度。来源中有示例。

我不会在旧帖子上详细介绍,但是如果您想了解更多,请添加评论,我会回到您身边。

我同意马特(Matt)的观点,即标题比步行缓冲区的页脚更好,因为作为PB是二进制协议,因此提出的页脚也不是有效的消息序列,这是有问题的。许多基于页脚的协议(通常是EOL程序)之所以可以使用,是因为消息内容在定义的范围内(通常为0x20-0x7f ASCII)。

一种有用的方法是让您的最低级别代码只需从套接字上读取缓冲区,然后将它们呈现到一个框架层,以组装完整的消息并记住部分(我提出了一种异步方法(使用CCR)) 这里, ,尽管有行协议)。

为了保持一致性,您始终可以将消息定义为带有三个字段的PB消息:固定式的长度,枚举为类型和包含实际数据的字节序列。这使您的整个网络协议保持透明。

TCP/IP以及UDP,数据包包括一些对其大小的引用。这 IP标头 包含一个16位字段,指定IP标头的长度 数据中的数据。这 TCP标头 包含一个4位字段,该字段用32位单词指定TCP标头的大小。这 UDP标头 包含一个16位字段,指定UDP标头的长度 数据中的数据。

这是事情。

无论您是在C#中使用System.net.sockets名称空间,还是Win32中的本机Winsock东西,都不会看到IP/TCP/UDP标头。这些标头被剥离,以便您在阅读插座时得到的是实际有效载荷,即发送的数据。

我从未见过的所有使用套接字完成的所有操作的典型模式是,您定义了要发送的数据之前的应用程序级标头。至少,此标头应包括要遵循的数据大小。这将使您能够完整阅读每个“消息”,而不必猜测其大小。您可以随心所欲,例如,同步模式,CRC,版本,消息类型等,但是“消息”的大小就是您 真的 需要。

就其价值而言,我建议使用标头而不是包装末端定界符。我不确定EOP定界符是否有显着的劣势,但是标题是我看到的大多数IP协议使用的方法。此外,从一开始就处理一条消息,而不是等待在我的流中出现一些模式以表明我的消息已经完成,这似乎对我来说似乎更为直观。

编辑:我只是知道Google协议缓冲区项目。据我所知,这是WCF的二进制序列化/除外序列化方案(我敢肯定这是一个过分简化的)。如果您使用的是WCF,则不必担心要发送的消息的大小,因为WCF管道会在幕后照顾它,这可能就是为什么您还没有在协议中找到与消息长度相关的任何内容缓冲文档。但是,就插座而言,如上所述,知道大小将极大地帮助您。我的猜测是,您将使用协议缓冲区序列化数据,然后在发送之前提出的任何应用程序标题上固定数据。在接收方面,您将删除标题,然后将其余的消息隔离化。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top