游戏服务器应该如何接收具有定义滴答率的 udp 数据包?

Posted

技术标签:

【中文标题】游戏服务器应该如何接收具有定义滴答率的 udp 数据包?【英文标题】:How should a game server receive udp packets with a defined tick rate? 【发布时间】:2019-01-24 23:23:12 【问题描述】:

我目前有一个可自定义滴答频率的游戏服务器,但对于本示例,我们建议服务器每秒或 1 赫兹仅滴答一次。我想知道如果客户端发送速率比服务器更快,因为我当前的设置似乎不起作用,那么处理传入数据包的最佳方法是什么。

我的 udp 阻塞接收在我的滴答函数中超时,它可以工作,但是如果客户端滴答速率高于服务器,则不会收到所有数据包;只有当前正在读取的那个。所以本质上服务器丢失了客户端发送的数据包。下图展示了我的问题。

所以我的问题是,这是如何正确完成的?是否有一个单独的线程不断读取数据包,排队,然后在服务器滴答时处理队列,还是有更好的方法?


图片取自视频https://www.youtube.com/watch?v=KA43TocEAWs&t=7s,但完全展示了我所解释的内容

【问题讨论】:

我很确定使用 UDP 协议的数据包不能保证传送,对吧?所以你必须建立一个像你描述的系统 @mad.meesh 是的,他们不能保证,但这不是我遇到的问题。也就是说,如果客户端发送了 50 个数据包,然后服务器滴答作响,它只读取最新的数据包,不知道其他数据包。我不确定这是否是 1hz 服务器的预期行为...... 我还没有使用 UDP 构建系统,但最重要的是,我正在考虑一些事情,您必须对客户端和服务器之间的传递进行一些验证,但是 .. 可能太慢了? 哦,好吧..是的,某种排队是有道理的,但很抱歉,我不知道给你一个可靠的答案 很惊讶没有人试图回答... 【参考方案1】:

你描述的场景有很多,但这是我的指导。

如果您以 1hz 运行服务器,则使用阻塞套接字阻止主逻辑循环运行并不是一个好主意。您可能无法以预期的速度接收消息(由于丢包、网络延迟峰值或客户端应用关闭)

A) 你当然可以创建另一个线程,继续阻塞 recv/recvfrom 调用,然后将它们排入线程安全数据结构中

B)您也可以只使用非阻塞套接字,并继续读取数据包,直到它返回 -1。操作系统会缓冲(通常是可配置的)一定数量的传入消息,直到如果您不阅读它就会开始丢弃它们。

无论哪种方式都可以,但是对于个人游戏客户端,我更喜欢第二种简单的方法,因为我知道我在一个以合理速率服务套接字的线程上(5hz 似乎很低,但可能适合你的游戏)。如果您有可能会停止服务线程(级别加载等),那么请使用第一种方法,这样如果您错过发送/接收定期保活消息,您就不会将其检测为断开连接。

在服务器端,如果我计划处理大量客户端/数据,我会竭尽全力有效地从套接字读取 - 在 Windows 上使用 IO 完成端口,或者在 Linux 上使用 epoll()。

【讨论】:

【参考方案2】:

您的服务器可能必须有一个线程每 5 秒计时一次,就像客户端接收所有数据包一样。在该滴答期间未收到的任何内容都将被丢弃,因为服务器没有在监听它。然后,您可以在 5 个滴答之后将数据从线程传递到服务器作为一个块。不过,更可靠的选择是将服务器设置为 5hz,就像客户端一样,并线程化来自客户端的每个数据包,这样它就不会锁定主线程。

例如,如果客户端更新率为 20,而服务器滴答率为 64,则客户端可能会在 20 滴答的服务器上播放。

【讨论】:

我不确定...这意味着每场比赛都必须有一个同步的客户端/服务器滴答率,而据我所见,他们没有。大多数时候,客户端的滴答率会比服务器的快,那么服务器如何处理额外的数据包。更重要的是如何在实际场景中处理这个问题,而不是我发布的场景。例如,如果我的客户端以 80hz 运行,而我的服务器以 60hz 运行,则有时您只是无法“将服务器设置为 80hz”,因为它需要在滴答窗口内执行大量处理。 那时您的客户端只能每 60hz 发送一次事件。我假设您将使用另外 20hz 的额外来处理渲染元素,因为它不会向服务器发送数据包。您可以发送每一个 80hz,但假设其余部分无论如何都会被丢弃。同样的问题发生在我的一些发送较短脉冲和一些发送较长重复脉冲的电子设备上。我要么没有收到信号,要么我得到了重复的过滤器。 我仍然认为这不能提供可靠的解决方案,除非我遗漏了一些东西。如果服务器以 30hz 运行而客户端以 60-70hz 运行,那么简单地将客户端降低到 30hz 并不是真正的解决方案,因为在某些情况下您希望客户端运行得更快。 在这篇文章中,他们讨论了一款以 20hz 运行的暴雪游戏,主要是因为他们不想给服务器带来压力。 kotaku.com/overwatchs-low-tick-rate-can-be-a-problem-1778708854。尽管在本文中他们比较了滴答率与 fps。尽管客户端可以以 240hz 的滴答率运行。并不意味着服务器会运行它。 nbnco.com.au/blog/entertainment/… 关于服务器滴答率的文章继续,但没有提及与我的问题相关的任何内容。我在帖子中添加了一张图片,更多地解释了我的问题。例如,从图片来看,一款流行游戏 Fortnite 的客户端发送速率约为 75hz,但服务器速率为 30hz。这是我遇到的问题,我想问如果客户端发送的数据包多于服务器可以处理的数据包,游戏如何解决此问题。甚至是 LawBreakers,客户端的频率为 170hz,而服务器的频率为 60hz。

以上是关于游戏服务器应该如何接收具有定义滴答率的 udp 数据包?的主要内容,如果未能解决你的问题,请参考以下文章

从使用 UdpClient 接收的 UDP 包中获取客户端 IP

如何在 Qt 中进行 UDP 打孔?

如何使时钟秒针以每秒 4 次跳动/滴答声移动?

如何发送具有确切大小的UDP数据包?

Udp发送端和接收端

多线程 Udp 服务器:将接收到的数据重定向到线程