例如,如果我在完全不同的数据包中发送“a”和“b”,客户端会将其读取为“ab”。它一次只发生一次,但它在游戏中造成了真正的问题。
我认为您忽略了 TCP 的基本性质:它是流协议,而不是数据包协议。TCP 既不尊重也不保留发送者的数据边界。换句话说,TCP 可以自由地组合(或拆分!)您发送的“数据包”,并以任何它想要的方式将它们呈现给接收器。TCP 遵守的唯一限制是:如果一个字节被传递,它将按照发送它的顺序传递。(Nagle 并没有改变这一点。)
因此,如果您在服务器上调用send
(或write
)两次,发送这六个字节:
"packet" 1: A B C
"packet" 2: D E F
您的客户端可能recv
(或read
)这些字节序列中的任何一个:
ABC / DEF
ABCDEF
AB / CD / EF
如果您的应用程序需要了解发送者之间的边界write
,那么您有责任保存和传输该信息。
正如其他人所说,有很多方法可以解决这个问题。例如,您可以在每个信息量之后发送一个换行符。这(部分)是 HTTP、FTP 和 SMTP 的工作方式。
您可以将数据包长度与数据一起发送。对此的通用形式称为 TLV,表示“类型、长度、值”。发送一个固定长度的类型字段,一个固定长度的长度字段,然后是一个任意长度的值。这样,您就知道何时读取了整个值并为下一个 TLV 做好了准备。
您可以安排您发送的每个数据包的长度都相同。
我想还有其他解决方案,我想您可以自己考虑。但首先你必须认识到这一点:TCP 可以并且将会合并或破坏你的应用程序包。您可以依赖字节传递的顺序,但仅此而已。