1

现在,我正在为我的在线游戏编写网络程序,但我不确定如何接收数据。问题是我无法真正猜测数据包的大小,所以我想从数据包中仅读取 4 个字节并将它们转换为 int 以了解数据包的大小。然后我将创建一个该大小的缓冲区并接收数据包的其余部分,这是个好主意吗?

供您参考,我使用的是非阻塞 i/o。

4

3 回答 3

1

您的方法听起来很合理-您实际上是将消息大小嵌入到消息标头中,这可能是在您的情况下处理它的最可靠的方法。或者,您可以使用固定长度的数据包(ick)或使用某种分隔符(这对于二进制消息根本不起作用)。

这个链接socket-protocol-fundamentals有一些额外的信息可能会有所帮助。

于 2010-03-23T21:24:40.823 回答
0

如果您使用 TCP 套接字,请不要依赖数据包大小。数据流是字节流,而不是数据包流。

于 2010-03-23T21:25:11.040 回答
0

如果您不小心,您所提出的就是一个正在形成的安全漏洞。所以要非常谨慎——尤其是在信任网络输入时。

您没有指定 TCP 或 UDP,所以我只是给您一些一般性的指导。

对于 TCP 或 UDP,只需分配一个大小为 N 的缓冲区,其中 N 是您可能从远程播放器或服务器发送的最大消息大小。对于 UDP,我建议将其保持在 1500 字节以下。对于 TCP,您可以有更大的尺寸。

对于您的套接字,无论是 UDP 还是 TCP,都使其成为非阻塞的。这样您就不会在等待数据时挂起游戏循环。

将大小和 crc-hash 添加到任何消息的标题中。当您以 UDP 数据包的形式接收消息时,如果数据包标头中的大小大于 N(这意味着您已经得到了一个截断的数据包)或哈希与您在接收大小上计算的不匹配,则拒绝数据包。我之所以这么说是因为没有额外的完整性检查,黑客和作弊者将利用您的数据包结构来获胜。

对于 TCP,您基本上按照您描述的方式构建消息。每条消息都有一个标头,指示要遵循的字节数。但是做与我呼吁 UDP 相同的事情 - 添加您自己的标头以进行完整性检查。如果您收到消息损坏和断言,请关闭套接字。

在 TCP 中,由于 TCP 分段,您可能不会在同一个“recv”调用中接收到整个消息。也就是说,如果您只收到部分消息,请将其存储在临时缓冲区中。在随后调用 recv 时(在下一个游戏帧上),追加到这个缓冲区。您必须保留变量以跟踪消息的预期结尾,这样您就不会意外读入可能已发送的下一条消息。

祝你好运。

于 2010-03-23T22:05:04.023 回答