CRLF vs LF vs 零网络协议设计

CRLF vs LF vs zero on network protocol design

我正在设计一个私有网络协议。我需要选择一个字符串分隔符。

如果分隔符是 [=11=]

,数据包将看起来像 string01[=10=]string02[=10=]string03[=10=]

该字符串不仅是 ascii,它是任何最终用户定义的编码字符串,如 utf8 或 base64 编码的二进制数据。

我的目的是做一个灵活且体积小的协议,所以字符串应该支持某种压缩算法。我想知道分隔符是否对此很重要。

如果编码是最终用户定义的,它可以包含 [=12=] 个字节,例如 UTF-16,因此 运行 长度编码的字符串可能效果最好:

\x08string01\x08string02\x08string03

或者,如果您需要超过 255 字节的字符串,请选择 2 字节(最大 65535)或更大的 big-endian(网络协议约定)值:

\x00\x08string01\x00\x08string02                 (ASCII)
\x00\x10\x00s\x00t\x00r\x00i\x00n\x00g\x000\x001 (UTF-16BE)

除了Mark已经提出的长度编码,还可以使用转义符。你设置了一个分隔符(比如 \0),如果 \0 出现在数据中,你在它前面放一个特殊的 "escape character" 来逃避它的特殊含义。这被某些协议使用,例如 HDLC:

...they use "control-octet transparency", also called "byte stuffing" or "octet stuffing". The frame boundary octet is 01111110, (7E in hexadecimal notation). A "control escape octet", has the bit sequence '01111101', (7D hexadecimal). If either of these two octets appears in the transmitted data, an escape octet is sent, followed by the original data octet with bit 5 inverted. For example, the data sequence "01111110" (7E hex) would be transmitted as "01111101 01011110" ("7D 5E" hex)

如果我是你,我会根据协议的版本假定字符串格式(即 ASCII 或 UTF8 或其他格式)。版本协议我认为你应该是协议握手(初始化)的一部分。例如:

 1. Client opens TCP connection to Server 
 2. Server> \x... <-- magic
 3. Server> \x01 <-- Protocol version 
 4. Client> \x00 <-- Ok

然后对字符串使用字符串终止使用数据大小 header 之前的字符串发送如下:

Client or Server> 0x000f <-- following data will be 100 bytes
Client or Server> .... // 100 of raw data is being transmitted and then decoded using the right encoding that is protocol coupled.

我认为这样协议更容易理解更容易扩展。