编写多人游戏服务器最合适的方法是什么?
What is the most appropriate way to write a multiplayer server?
我目前正在为快节奏多人游戏编写服务器,它应该是 运行 UDP (我读到 TCP 在应用程序中处理丢包的方式不合适需要及时传送数据,如果 TCP 更有用请指正) 游戏不是多人多人游戏,应该主要由玩家自己托管,可能在本地专用服务器上。虽然我很确定客户端需要在 NIO 中,以避免网络问题导致游戏延迟,但我还不知道如何编写服务器。以下是我考虑过的可能性列表:
- 为每个播放器使用单独的线程,每个播放器都绑定一个套接字
- 使用一个套接字遍历每个玩家
- 做同样的事情,但使用 NIO
- 使用一个套接字同时向所有客户端广播消息
- 在单独的线程上使用一个套接字进行接收,一个用于发送
以下哪种方法最适合在客户端数量相对较少的情况下处理时间紧迫的数据?(不超过 16 个)
TCP 有更多的开销,导致传输相同信息需要更高的带宽。然而,TCP 确实具有在未到达时被重新发送的优势。如果您使用 UDP,请确保您通过网络发送的消息不会丢失。例如,如果您将动作作为添加和更改发送,那么它将很快与客户失去同步。传输时需要覆盖值。
每个玩家都需要一个线程来监听他们的输出,例如击键或动作,因为您必须等待每个线程上的数据,因此它会阻塞玩家 1,直到他们做出动作和玩家 2在玩家 1 之前无法采取行动。
广播游戏状态可能有意义 - 但我没有这方面的经验,也没有像快节奏多人游戏那样时间紧迫的东西
对于 16 个客户端,除非您的硬件非常糟糕,或者您进行了一些离谱的处理,否则无论哪种方式,您的性能都会很好。这意味着您可以以任何方式编写它,使您编写和维护起来更简单。
关于您的选择的几句话:
Using separate thread for each player with a socket bound to each
这种方法对于数量较少的 TCP 套接字更有意义。如果您使用 UDP,则只有一个套接字,因此没有必要。但是,如果您的游戏需要对每个客户端进行一些并行处理,那么为每个客户端设置一个线程会很有用。
Using one single socket to loop through every player
这可能是最简单的选择,除非您的游戏要求非常特殊。正如我之前所说,您应该在性能方面表现出色。因此,如果它使编写代码更容易,那就去做吧。避免 premature optimizations.
using one socket for receiving, and one for sending on a separate
thread
除非你有充分的理由这样做,否则我会避免这个想法。它可能(不必要地)使网络方面的事情变得复杂,因为客户端将向端口 X 发送数据包,并从端口 Y 获得回复。NAT 将是一个严重的问题。
using one socket to broadcast messages to all clients simultaneously
首先,这只能在一个方向上起作用——从服务器到客户端。其次,这只会起作用 inside a LAN 因为路由器不转发广播数据包。如果您接受这两个限制并发现自己设计了一个系统,其中服务器向所有玩家(至少向同一网络中的玩家)发送一些数据包,那么这可能不是一个坏主意。就性能而言,除非您发送大量数据包,否则您可能不会注意到向每个玩家发送单独副本与发送广播之间的区别。
我目前正在为快节奏多人游戏编写服务器,它应该是 运行 UDP (我读到 TCP 在应用程序中处理丢包的方式不合适需要及时传送数据,如果 TCP 更有用请指正) 游戏不是多人多人游戏,应该主要由玩家自己托管,可能在本地专用服务器上。虽然我很确定客户端需要在 NIO 中,以避免网络问题导致游戏延迟,但我还不知道如何编写服务器。以下是我考虑过的可能性列表:
- 为每个播放器使用单独的线程,每个播放器都绑定一个套接字
- 使用一个套接字遍历每个玩家
- 做同样的事情,但使用 NIO
- 使用一个套接字同时向所有客户端广播消息
- 在单独的线程上使用一个套接字进行接收,一个用于发送
以下哪种方法最适合在客户端数量相对较少的情况下处理时间紧迫的数据?(不超过 16 个)
TCP 有更多的开销,导致传输相同信息需要更高的带宽。然而,TCP 确实具有在未到达时被重新发送的优势。如果您使用 UDP,请确保您通过网络发送的消息不会丢失。例如,如果您将动作作为添加和更改发送,那么它将很快与客户失去同步。传输时需要覆盖值。
每个玩家都需要一个线程来监听他们的输出,例如击键或动作,因为您必须等待每个线程上的数据,因此它会阻塞玩家 1,直到他们做出动作和玩家 2在玩家 1 之前无法采取行动。
广播游戏状态可能有意义 - 但我没有这方面的经验,也没有像快节奏多人游戏那样时间紧迫的东西
对于 16 个客户端,除非您的硬件非常糟糕,或者您进行了一些离谱的处理,否则无论哪种方式,您的性能都会很好。这意味着您可以以任何方式编写它,使您编写和维护起来更简单。
关于您的选择的几句话:
Using separate thread for each player with a socket bound to each
这种方法对于数量较少的 TCP 套接字更有意义。如果您使用 UDP,则只有一个套接字,因此没有必要。但是,如果您的游戏需要对每个客户端进行一些并行处理,那么为每个客户端设置一个线程会很有用。
Using one single socket to loop through every player
这可能是最简单的选择,除非您的游戏要求非常特殊。正如我之前所说,您应该在性能方面表现出色。因此,如果它使编写代码更容易,那就去做吧。避免 premature optimizations.
using one socket for receiving, and one for sending on a separate thread
除非你有充分的理由这样做,否则我会避免这个想法。它可能(不必要地)使网络方面的事情变得复杂,因为客户端将向端口 X 发送数据包,并从端口 Y 获得回复。NAT 将是一个严重的问题。
using one socket to broadcast messages to all clients simultaneously
首先,这只能在一个方向上起作用——从服务器到客户端。其次,这只会起作用 inside a LAN 因为路由器不转发广播数据包。如果您接受这两个限制并发现自己设计了一个系统,其中服务器向所有玩家(至少向同一网络中的玩家)发送一些数据包,那么这可能不是一个坏主意。就性能而言,除非您发送大量数据包,否则您可能不会注意到向每个玩家发送单独副本与发送广播之间的区别。