假设你想做一个实时游戏,也许是一个2D俯视游戏。为了保持简单,您将在游戏中做的事情是:
- 连接到服务器
- 使用按键移动播放器
- 可能按空格键进行攻击
- 发送聊天消息
但是,如果来自任何这些情况的数据报丢失,会发生什么?你会怎么做?
1) 连接到服务器
如果您向服务器发送 UDP 数据报,服务器将获取您的 IP 和端口,然后创建一个播放器根据它给你的 ID,这是它每次收到你的数据报时识别你的方式。
但是,如果在"连接"(实际上不是连接,只是一个 udp 数据报,上面写着"让我成为您服务器的一部分")时,这个初始数据报丢失了怎么办。如果一段时间后您没有收到来自服务器的回复,那么说您只会重新发送它是正确的吗?
2)移动球员/攻击
如果在任何时候我们移动播放器/按移动键/攻击键,我们会发送击键服务器告诉它我们按下/释放了什么键。然后,服务器会将其中继到所有其他客户端。
但是,如果此击键数据报丢失怎么办?在客户端>服务器或服务器>客户端上。因为击键一直在发生,所以一直重新发送它是否有效?或者我们会忽略它在此过程中丢失的事实,因为如果您再次按下某个键,它很可能会在下次成功?
3) 发送聊天消息
这将是必须到达服务器的东西。如果途中丢失了,一段时间后,如果我们没有收到对方/接收端的回复,我们是否重新发送?
博士
如果我们知道在一段时间后没有达到数据报,是否可以继续重新发送数据报?另外,确认数据报是否成功发送呢?
如果客户端向服务器发送聊天消息,并且服务器收到它,服务器是否应该向客户端发送回复以确认它收到了它?如果那个回复丢失了,会发生什么,然后呢?
通常,使用 UDP 的游戏在顶部具有应用程序级协议,因此它们可以可靠地发送一些消息,而其他消息则不然。如果他们想可靠地发送所有内容,他们最好使用 TCP。然而,快节奏的游戏无法承受TCP引入的延迟,如果数据包确实丢失了,重新发送它通常为时已晚!
实现可靠消息的一种方法是,就像您想象的那样,发送一个 ACKnowledgment 回复,表示已收到此特定数据包 - 但是如果您问如果丢弃怎么办?可靠数据包的发送方通常会重新发送一定次数(例如 3 次),如果仍然没有收到 ACK,则发送方假设对等方已丢弃。
文章和游戏网络的绝佳场所,包括如何最小化发送的数据是Shawn Hargreaves博客。(这主要集中在 C# XNA,但无论语言/框架/平台如何,都适用相同的逻辑)。
最后:
- 快节奏游戏的游戏网络编程很难。如果您的游戏速度较慢和/或基于回合制,请考虑 TCP 和锁步方法,这使事情变得相当容易。
- 不要重新发明轮子,有些库可以做一些事情,例如在需要时在UDP之上实现可靠性,例如FalconUDP。虽然这是一个.NET-我希望看到一个Java端口:)
如果数据报丢失,接收者无能为力,因为他不知道。由发送方重新发送,由你来设计基于 ACK 或基于 NACK 的协议,以便接收方知道何时执行此操作。
继续重新发送 UDP 数据报取决于服务器如何处理数据报中的数据。 例如,如果您重新发送聊天消息,并且服务器同时收到原始消息和重新发送的消息,服务器是否显示该消息两次? 请注意,即使收到原始邮件,您最终也可能重新发送,因为对原始邮件的回复可能已丢失或延迟。
最好的办法是使用TCP而不是UDP,因为TCP已经为您解决了所有这些问题。 例如,《魔兽世界》从TCP开始用于聊天,UDP用于游戏,最终转换为TCP。