The choice of a suitable network topology is critical for effective and stable multiplayer. We'll talk about the pros and cons of the main network topologies for real-time multiplayer: P2P, authoritative servers, relay servers, and more.
Greetings again everyone, I'm Dmitrii Ivashchenko, Lead Software Engineer at MY.GAMES. Our article series on the landscape of Unity realtime multiplayer in 2023 continues — and today's topic concerns the main network topologies for realtime multiplayer.
The key factor in ensuring the effective and stable operation of a multiplayer game is the choice of a suitable network architecture, or topology. This decision affects both the way data is transmitted and processed in the game, as well as performance and resource consumption. Let's look at some possible models.
P2P, or peer-to-peer architecture, is a model in which each player connects to every other player and exchanges data about game state and events. In “pure” P2P, there is no single "host". Instead, each client is responsible for managing its own game character (or units) while receiving updates about events from each of the other clients.
Advantages of P2P:
No need to develop or maintain dedicated servers.
Clients create direct connections with each other, providing the most direct connection (which usually, but not always, corresponds to a low ping).
Disadvantages of P2P:
In this model, one of the nodes of the game network (this is usually initially selected or based on network connection features) becomes the "authoritative server", controlling the game state and processing all game events. The other nodes (clients) send their actions to this server and receive updated game state from it.
In a client-server architecture with an authoritative dedicated game server, all clients connect to a single game server. The dedicated game server (DGS) runs the game engine and is the source of the game's final state. It receives updates from connected clients, incorporates them into its game state, and sends the resulting state to each client.
MMORPGs and other games with persistent online worlds also fall into this category. In such cases, DGS also includes databases that store data about the persistent world.
Advantages of DGS:
Disadvantages of DGS:
Leveraging a client-server architecture with an authoritative dedicated game server is one of the most common approaches in large multiplayer games and provides a high degree of control over the state of the game and combating fraud.
In a client-server architecture with an authoritative client-host, instead of using a dedicated game server to maintain authoritative game state, it's possible to use one of the client machines as a server. This client becomes a client-host; simultaneously the host of the game session as well as a participant in the game.
Advantages of client-host:
Disadvantages of client-host:
The client-server architecture with an authoritative client-host allows players to independently organize multiplayer sessions without the need to connect to a dedicated game server. However, it's necessary to consider the load on the host machine and potential issues with "host advantage".
In architecture with a relay/matchmaking server for finding opponents, the server exists to facilitate connections and data transmission between clients, but does not actively participate in the game.
Although a dedicated server is still required because it does not need to run a game engine, creation and management of this can be relatively inexpensive. Moreover, most P2P games can easily switch to using a relay server, since the network code only differs in the way clients connect to each other.
Advantages of relay servers:
Disadvantages of relay servers:
The relay/server architecture for finding opponents provides a simple and inexpensive solution for ensuring connections and data transmission between clients. It avoids problems related to port forwarding and firewalls, but it may have some delay due to the intermediate server.
Here's an example of the RelayServer
class in C# that uses TCP to listen for incoming client connections and then add them to a list of active clients. The server then asynchronously handles each client connection by reading data and forwarding it to all connected clients:
public class RelayServer
{
private TcpListener _listener;
private List<TcpClient> _clients = new List<TcpClient>();
public async Task StartAsync(int port)
{
_listener = new TcpListener(IPAddress.Any, port);
_listener.Start();
Console.WriteLine($"Server started on port {port}");
while (true)
{
TcpClient client = await _listener.AcceptTcpClientAsync();
_clients.Add(client);
Task.Run(() => HandleClientAsync(client));
}
}
}
The code below represents the function HandleClientAsync
, which is responsible for processing each connected client in asynchronous mode.
First, the function creates a buffer for reading data and obtains a stream for reading and writing data. Next, in an infinite loop, the function asynchronously reads data from the stream. If no data is received (i.e. the client disconnected), the function removes the client from the list and stops processing. Otherwise, the received data is converted to a string and sent to all connected clients:
private async Task HandleClientAsync(TcpClient client)
{
byte[] buffer = new byte[1024];
NetworkStream stream = client.GetStream();
while (true)
{
int bytesRead = await stream.ReadAsync(buffer, 0, buffer.Length);
if (bytesRead == 0)
{
_clients.Remove(client);
return;
}
string message = Encoding.UTF8.GetString(buffer, 0, bytesRead);
BroadcastMessage(message);
}
}
To send the received message to all connected clients, we will need the function BroadcastMessage
:
private void BroadcastMessage(string message)
{
foreach (var client in _clients)
{
NetworkStream stream = client.GetStream();
byte[] buffer = Encoding.UTF8.GetBytes(message);
stream.Write(buffer, 0, buffer.Length);
}
}
The function takes a message as a string, iterates through the list of connected clients, and for each of them converts the message to bytes and writes it to the corresponding network connection stream. This way, the message is successfully transmitted to all clients.
In this article, we discussed the main network topologies for real-time multiplayer games — including P2P, authoritative server, and relay server. Each topology has its advantages and disadvantages, such as direct connections and low ping in P2P, and effective cheat detection and fraud prevention in authoritative server; relay server provides a simple and inexpensive solution for ensuring connections and data transmission between clients.
Choosing the right topology is crucial for ensuring a smooth gaming experience in real-time multiplayer games. But this decision also concerns infrastructure cost and project scalability.
In the next article, we will consider the main patterns of network architecture in different game genres.