0

我有一个带有 GUI 的 C++ 应用程序,它像网络游戏一样运行(在 PC 1 上),并以相当固定的时间间隔(如 40 毫秒)通过 WiFi(ad-hoc,因此非常可靠)从另一台计算机(2)接收数据包, 程序 (2) 上的每个循环一次。我使用发送/读取。

这是问题所在:
- 数据包并不总是完全发送(但显然你可以简单地保留send()剩余的数据,直到所有数据都发送完毕,这很好)
-更重要的是,数据包在(1)的循环期间堆叠在套接字中直到read()发生,然后就无法区分大数据流中的数据包,或者知道您是否已经在数据包的中间。

我试图用 ID 头来解决这个问题(你发现一个 ID 作为第一个字节并且你知道数据包的长度),但我经常迷路(未知 ID:我们不在数据包的开头)并且被迫忽略所有剩余的数据。

所以我的问题是:
为什么数据包会堆叠?(通常我有 400B 的数据,而我的数据包长度 <100B 并且 fps (1) 和 (2) 差别不大)
我怎样才能有更可靠的方式来接收实际数据包,比如 80% 的数据包(丢弃数据包丢失,不是UDP/TCP的问题)?

用于接收数据包的单独线程会起作用吗?(在 (1) 上,服务器)

实时网络游戏如何做到这一点(包括多客户端管理)?

提前致谢。

(对不起,我这里没有代码,但我尽量说清楚)

4

3 回答 3

4

好:

1) UDP 传输 MESSAGES,但不可靠。

2) TCP 传输 BYTE STREAMS,并且是可靠的。

UDP 不能可靠地传输消息。任何更可靠的东西都需要基于 UDP 的协议。

TCP 不能传输消息,除非它们是一个字节长。任何更复杂的东西都需要基于 TCP 的协议。

于 2012-08-23T14:08:34.700 回答
0
  • 数据包为什么要堆叠?(通常我有 400B 的数据,而我的数据包长度小于 100B,fps (1) 和 (2) 差别不大)

因为通过网络发送数据包的时间会有所不同,所以以高速率发送数据包通常没有意义,因此大多数网络库(例如 RakNet)会将数据包排队并每 10 毫秒发送一次。

在 TCP 的情况下,有 Nagle 算法,它是做同样事情的一种更有原则的方法。您可以通过设置 NO_DELAY TCP 标志来关闭 Nagle。

  • 我怎样才能有一种更可靠的方式来接收实际的数据包,比如 80% 的数据包(丢弃数据包丢失,这不是 UDP/TCP 的问题)?

如果您使用 TCP,您将按正确的顺序接收所有数据包。使用 TCP 的惩罚是如果一个数据包被丢弃,它之后的数据包会等到该数据包可以在处理之前重新发送。这会导致明显的延迟,因此任何使用 TCP 的游戏都具有复杂的预测技术来隐藏这种延迟和其他技术,以便在丢失的数据包到达时顺利“赶上”。

如果您使用 UDP,您可以在顶部实现一个层,该层为您提供可靠性,但如果数据包的顺序无关紧要,则通过发送每个数据包的计数器并让接收器重复通知发送者计数中的间隙. 你也可以通过做类似的事情来实现排序。当然,如果您同时执行这两种方法,那么您就是在创建自己的 TCP 层。有关详细信息,请参阅http://www.jenkinssoftware.com/raknet/manual/reliabilitytypes.html 。

于 2012-08-23T16:04:53.790 回答
0

您所描述的是,如果您使用没有协议的 TCP 来构建传输的数据会发生什么。您使用 ID 标头和数据包长度的想法就是这样一种协议。如果您发送一个 4 字节的 ID,后跟一个 4 字节的长度,然后是 X 个字节,那么接收方知道它必须读取 4 个字节,然后是 4 个字节,然后是 X 个字节才能接收完整的数据包。没有比这更简单的了。您仍然无法使用如此简单的协议读取数据包这一事实表明您的底层套接字读取代码一开始就有缺陷。如果没有看到你的实际代码,很难告诉你你做错了什么。

于 2012-08-23T20:18:58.840 回答