2009-06-25 43 views
9

我正要写一个通过TCP流的消息协议。接收者需要知道消息边界在哪里。写一个流协议:消息大小字段或消息分隔符?

我可以发送1)固定长度的消息,2)大小字段,因此接收者知道消息有多大,或者3)唯一的消息终止符(我想这不能用在消息的任何其他地方) 。

为了提高效率,我不会使用#1。

我喜欢#2,但它有可能使流不同步?

我不喜欢想法#3,因为它意味着接收者无法提前知道消息的大小,并且还要求终结符不会出现在消息的其他地方。

#2,如果有可能不同步,我可以添加一个终止符,或者我保证永远不会失去同步,只要发送者程序发送的内容是正确的。是否有必要做#2 AND#3?

请让我知道。

感谢, JBU

回答

5

您使用的是TCP,数据包传送的可靠性。所以连接要么丢失,要么超时,要么读完整条消息。 所以选项#2是好的。

3

根据您的工作级别,#2实际上可能不会出现与同步不同步的问题(TCP在数据包中包含序列号,并且如果到达时按照正确的顺序为您重新组装流无序)。

因此,#2可能是您最好的选择。此外,在传输过程中尽早了解消息的大小会使接收端更容易分配内存。

+0

_另外,在传输的早期就知道消息的大小,这样可以更容易地在接收端分配内存。一句关心的话:确保限制分配多少内存。否则,您很容易受到使用自定义数据包的DDoS攻击,这些数据包的大小字段为2^32-1(或者您的整数大),从而快速填满您的内存。 – Kenji 2017-04-21 18:13:48

1

如果您是从头开发传输和接收代码,那么使用长度头文件和分隔符都不会有什么坏处。这将提供健壮性和错误检测。考虑一下你只使用#2的情况。如果您向TCP流中写入长度为N的字段,但最终发送的消息大小与N不同,则接收端不会知道任何更好的消息,并最终导致混淆。

如果同时使用#2和#3,虽然不是万无一失,但如果在从TCP流中消耗N个字节后遇到分隔符,则接收方可以更加确信它收到了正确的消息。您还可以安全地在邮件中使用分隔符。

查看HTTP Chunked Transfer Coding了解使用#2和#3的真实世界示例。

2

我同意sigjuice。 如果您有一个大小字段,它不是必需添加和消息结束分隔符 - 但是,这是一个好主意。两者都使得事情更健壮,更容易调试。

考虑使用标准netstring format,其中包括一个大小字段和一个字符串结束字符。 因为它有一个大小字段,所以在消息内部使用字符串末尾字符是可以的。

0

还有第四种选择:自描述协议,如XML。

+0

这不适用于纯二进制消息。它基本上是选项#3,但比单个分隔符差得多。 – Lucretiel 2015-01-06 20:38:07

2

有趣的是,这里没有明确的答案。无论如何,#2对于TCP来说都是安全的,并且经常在“现实世界”中完成。这是因为TCP保证所有的数据都是无损的并且按照发送的顺序到达,因此正确的实现不可能不同步。