C# 如何检测何时完全接收到协议缓冲区消息?

C# 如何检测何时完全接收到协议缓冲区消息?,c#,networking,sockets,protocol-buffers,C#,Networking,Sockets,Protocol Buffers,这是我的一个分支。如果你愿意,可以读一读,但没必要 基本上,我意识到为了在大型消息上有效地使用C#的BeginReceive(),我需要(a)首先读取数据包长度,然后精确读取那么多字节,或者(b)使用数据包结束分隔符。我的问题是,协议缓冲区中是否存在这两种类型?我还没有使用它们,但是在查看文档时,似乎没有长度标题或分隔符 如果没有,我该怎么办?我是否应该构建消息,然后在其前面/后面加上长度头/EOP分隔符?您需要在协议中包含大小或结束标记。基于流的套接字(TCP/IP)中没有内置任何东西,只支持

这是我的一个分支。如果你愿意,可以读一读,但没必要

基本上,我意识到为了在大型消息上有效地使用C#的BeginReceive(),我需要(a)首先读取数据包长度,然后精确读取那么多字节,或者(b)使用数据包结束分隔符。我的问题是,协议缓冲区中是否存在这两种类型?我还没有使用它们,但是在查看文档时,似乎没有长度标题或分隔符


如果没有,我该怎么办?我是否应该构建消息,然后在其前面/后面加上长度头/EOP分隔符?

您需要在协议中包含大小或结束标记。基于流的套接字(TCP/IP)中没有内置任何东西,只支持将不确定的八位字节流任意分解为单独的数据包(数据包也可以在传输过程中被拆分)

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

可选地,可以添加带有校验和甚至加密签名的消息页脚(固定大小)(取决于您的可靠性/安全性要求)

知道有效负载大小允许您继续读取足够消息其余部分的字节数(如果读取完成的字节数较少,则对剩余字节进行另一次读取,直到接收到整个消息为止)


有一个结束消息指示器也可以工作,但是您需要定义如何处理包含相同八位字节序列的消息…

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

事情是这样的

使用Windows中的标准常规套接字,无论您是使用C#中的System.Net.sockets命名空间还是Win32中的本机Winsock内容,都不会看到IP/TCP/UDP头。这些头被剥离,以便在读取套接字时得到的是实际的有效负载,即发送的数据

我所见过的和使用套接字所做的一切的典型模式是,在要发送的数据之前定义一个应用程序级头。此标题至少应包含要遵循的数据的大小。这将允许您完整地阅读每个“消息”,而无需猜测其大小。您可以随心所欲地使用它,例如同步模式、CRC、版本、消息类型等,但“消息”的大小才是您真正需要的

值得一提的是,我建议使用报头而不是数据包结束分隔符。我不确定EOP定界符是否有明显的缺点,但头部是我见过的大多数IP协议使用的方法。此外,对我来说,从一开始就处理消息似乎更直观,而不是等待流中出现某种模式来指示消息已完成


编辑:我刚刚意识到谷歌协议缓冲区项目。据我所知,这是一个针对WCF的二进制序列化/反序列化方案(我确信这是一个严重的过度简化)。如果您使用的是WCF,则不必担心发送的消息的大小,因为WCF管道会在幕后处理这些问题,这可能就是为什么您在Protocol Buffers文档中找不到任何与消息长度相关的内容。然而,对于套接字,如上所述,知道大小将非常有帮助。我的猜测是,您将使用协议缓冲区序列化数据,然后在发送数据之前附加任何应用程序头。在接收端,您将删除页眉,然后对消息的其余部分进行反序列化。

我同意Matt的观点,即对于协议缓冲区而言,页眉比页脚更好,主要原因是,由于PB是一个二进制协议,因此产生一个不也是有效消息序列的页脚是有问题的。许多基于页脚的协议(通常是EOL协议)都可以工作,因为消息内容在定义的范围内(通常是0x20-0x7F ASCII)

一种有用的方法是让最低级别的代码从套接字中读取缓冲区,并将它们呈现给一个框架层,该层组装完整的消息并记住部分消息(我提供了一种异步方法(使用CCR),尽管是针对行协议)


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

对晚会迟到表示歉意。我是protobuf net的作者,它是C#实现之一。对于网络使用,您应该考虑“[De] SerialZeIn LosithPrime'”方法——这样,它将自动为您处理长度。源代码中有一些示例


我不会在一篇旧文章中详细介绍,但如果你想知道更多,请添加评论,我会回复你。

如果你是指protobuf net,不,它不仅仅是针对WCF;项目中有一些套接字示例。