回答旧消息,因为有一些东西需要纠正:
与此处声称的许多答案不同,TCP 不保证数据完好无损地到达。甚至实际上都没有。
TCP 协议有一个 2 字节的 crc 校验和,如果超过一位翻转,显然有 1:65536 的碰撞机会。这是一个很小的机会,它永远不会在测试中遇到,但是如果您正在开发的东西要么传输大量数据和/或被非常多的最终用户使用,那么这个骰子就会被抛出数万亿次(不是开玩笑,youtube每个用户每秒抛出大约 30 次。)
选项 2:由于您自己列出的原因,尺寸字段是唯一实用的选项。固定长度的消息会很浪费,并且分隔符标记需要通过某种编码-解码阶段运行整个有效负载,以替换至少三个不同的符号:开始符号、结束符号和表示已发生替换的替换符号。
除此之外,很可能希望使用某种带有严重校验和的错误检查。可能与加密协议一起实现作为消息有效性检查。
至于不同步的可能性:每条消息都有可能,但有补救措施。
一个有用的方案是每条消息都以标头开头。此标头可以非常短(<30 字节),并包含消息有效负载长度、有效负载的最终正确校验和以及标头本身的第一部分的校验和。消息也将具有最大长度。这种短标题也可以用已知符号来定界。
现在接收端将始终处于以下两种状态之一:
- 等待新的消息头到达
- 接收更多数据到正在进行的消息,其长度和校验和是已知的。
这样,接收方在任何情况下最多会在一条消息的最大长度内不同步。(假设消息长度字段中存在损坏的标头)
使用这种方案,所有消息都作为离散的有效载荷到达,即使中间有恶意破坏的数据,接收方也不会永远卡住,到达有效载荷的长度是预先知道的,并且成功传输的有效载荷已经通过额外的更长校验和来验证,并且校验和本身已经过验证。所有这些的开销可能只是一个包含三个 64 位字段和两个定界符号的 26 字节标头。
(标头不需要替换编码,因为它只在一个正在进行的消息状态中被预期,并且整个 26 个字节可以一次处理)