使用Winsock接收数据

发布于 2024-08-26 10:36:07 字数 163 浏览 11 评论 0原文

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

供您参考,我使用的是非阻塞 I/O。

Right now, I'm programming the networking for my online game, and I'm not really sure
what to do about receiving data.
The problem is that I can't really guess the packet's size, so I thought of reading just 4 bytes from the packet and converting them to an int to know what's the packet's size.
Then I'll just create a buffer in that size and receive the rest of the packet, is that a good idea?

For your information, I'm using non-blocking i/o.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

纵性 2024-09-02 10:36:08

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

此链接 socket-protocol-fundamentals 有一些可能有帮助的附加信息。

Your approach sounds reasonable - you would essentially be embedding message size into a message header, which is likely the most robust way to handle it in your situation. Alternatively you could either use fixed length packets (ick) or use some sort of delimeter character (which will NOT work well at all for binary messages).

This link socket-protocol-fundamentals has some additional information which might help.

似梦非梦 2024-09-02 10:36:08

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

If you are using TCP sockets, NEVER rely on packet size. The data flow is a stream of bytes, not a stream of packets.

野生奥特曼 2024-09-02 10:36:08

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

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

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

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

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

对于 TCP,您基本上按照您所描述的方式构建消息。每条消息都有一个标头,指示后面的字节数。但请按照我对 UDP 的要求执行相同的操作 - 添加您自己的标头以进行完整性检查。如果收到消息损坏和 ASSERT,请关闭套接字。

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

祝你好运。

If you aren't careful, what you are proposing is a security hole in the making. So be very cafeful - especially when trusting network input.

You didn't specify TCP or UDP, so I'll just give you some general guidance.

For TCP or UDP, just allocate a single buffer of size N, where N is the biggest message size you could possibly have sent from the remote player or server. For UDP, I'd recommend keeping this under 1500 bytes. For TCP, you could have larger sizes.

For your socket, whether UDP or TCP, make it non-blocking. This is so you don't hang the game loop while waiting for data.

Add a size and crc-hash to the header of any message. When you receive the messsage as a UDP packet, if the size in the packet header is bigger than N (which means you've already got a truncated packet) or the hash doesn't match what you compute on the receive size, just reject the packet. I call this out because without additional integrity checks, hackers and cheaters will exploit your packet structure to win.

For TCP, you essentially frame your messages as the way you describe. Each message has a header dictating the number of bytes that are to follow. But do the same stuff as I call out for UDP - add a header of your own for integrity checking. Close the socket if you ever get message corruption and ASSERT.

In TCP, because of TCP segmentation, you may not receive the entire message in the same "recv" call. That is, if you only received a partial message, store it in temporary buffer. On a subsequent call to recv (on the next game frame), append to this buffer. You'll have to keep variables to track the expected end of the message so you don't accidentally read into the next message that may have been sent.

Good luck.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文