【问题标题】:To pad or not to pad - creating a communication protocol填充或不填充 - 创建通信协议
【发布时间】:2010-10-26 09:19:04
【问题描述】:

我正在创建一个协议,让两个应用程序通过 TCP/IP 流进行通信,并且正在研究如何为我的消息设计标头。使用 TCP 标头作为初始指南,我想知道是否需要填充。我知道,当我们处理缓存时,我们希望确保存储的数据适合一行缓存,以便在检索数据时高效完成。但是,考虑到应用程序将解析字节流并将其存储为它认为合适的方式,我不明白填充标头有何意义。

例如:我想通过一个包含 3 字节字段和后跟 1 字节填充字段的消息头发送 32 位对齐。然后我将发送消息数据。

在这种情况下,接收者只会从流中取出 3 个字节并丢弃填充字节。然后开始读取消息数据。正如我所看到的,他不会以他想要的方式存储 3 个字节和消息数据。字节对齐的全部意义在于以一种有效的方式对其进行检索。但是如果检索器不关心填充,如何有效地检索它?

没有填充,检索器仅从流中获取 3 个标头字节,然后获取数据字节。既然检索器按照自己的意愿存储这些字节,那么填充是否完成又有什么关系呢?

也许我错过了填充点。

从这篇文章中提取一个问题有点困难,但我所说的你们可能会指出我的误解。

请让我知道你们的想法。

谢谢, jbu

【问题讨论】:

    标签: protocols communication padding


    【解决方案1】:

    如果邮件正文的字对齐有一些用处,那么一定要填充邮件以避免其他扭曲。如果大部分消息被处理为具有适当强度的机器词,则填充将是有益的。

    如果消息是字节流,例如 xml,那么填充不会给你带来很多好处。

    就实际设计有线协议而言,您可能应该考虑使用带有压缩功能的纯文本协议(包括标头),这可能会比您可能发明的任何手工设计的二进制协议使用更少的带宽。

    【讨论】:

    • +1 将文本用于可读性、调试、日志记录、可扩展性等,和/或压缩文本以最小化大小;二进制格式很可能是“过早的优化”。不过,二进制格式可能优化 CPU 利用率和内存,这是 TCP 的一个重要考虑因素(对于本土协议/应用程序可能重要也可能不重要)。
    【解决方案2】:

    考虑到应用程序将解析字节流并以它认为合适的方式存储它,我不明白填充标头有何意义。

    如果我是接收者,我可能会将一个缓冲区(即一个字节数组)传递给协议驱动程序(即 TCP 堆栈)并说,“当其中有数据时将其还给我”。

    然后,我(应用程序)返回的是一个包含数据的字节数组。使用 C 风格的技巧,如“强制转换”等,我可以将此数组的某些部分视为单词和双字(不仅仅是字节)......只要它们适当对齐(这是填充可能的位置必填)。

    这是一个从字节缓冲区中的偏移量读取 DWORD 的语句示例:

    DWORD getDword(const byte* buffer)
    {
      //we want the DWORD which starts at byte-offset 8
      buffer += 8;
      //dereference as if it were pointing to a DWORD
      //(this would fail on some machines if the pointer
      //weren't pointing to a DWORD-aligned boundary)
      return *((DWORD*)buffer);
    }
    

    这是Intel汇编中的对应函数;请注意,它是单个操作码,即访问数据的一种非常有效的方式,比读取和累积单独的字节更有效:

    mov eax,DWORD PTR [esi+8]
    

    【讨论】:

      【解决方案3】:

      考虑填充的一个原因是如果您计划随着时间的推移扩展您的协议。可以有意留出一些填充以供将来分配。

      考虑填充的另一个原因是在长度字段上节省几个位。 IE。总是 4 或 8 的倍数可以节省长度字段的 2 或 3 位。

      【讨论】:

        【解决方案4】:

        TCP 具有填充(可能不适用于您)的另一个很好的原因是它允许专用网络处理硬件轻松地将数据与标头分开。由于数据始终以 32 位边界开始,因此在路由数据包时更容易将标头与数据分开。

        【讨论】:

          【解决方案5】:

          如果您有一个 3 字节的标头并将其对齐为 4 个字节,则将未使用的字节指定为“保留供将来使用”并要求这些位为零(拒绝格式不正确的消息)。这给你留下了一些可扩展性。或者您可能决定将字节用作版本号 - 最初为零,然后如果(何时)您对协议进行不兼容的更改,则将其递增。不要让值是“未定义”和“不在乎”;如果你以这种方式开始,你将永远无法使用它。

          【讨论】:

            猜你喜欢
            • 2017-04-27
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2015-07-13
            • 2016-10-10
            • 1970-01-01
            • 2015-04-09
            相关资源
            最近更新 更多