Network architecture is a complicated topic. That is true without including the game part. In this article I will try to simplify the main concepts so that they become more clear. After reading this you should have a general high-level idea of how to implement a working and scalable network architecture for your game.
This is part of a series where I explain how a network game can be created easily. In examples here I will mostly talk about python and the Godot game engine but the concepts are applicable to other languages and game engines. If you want to look into other topics regarding implemntation you can start with:
Table of Contents
- Elements of a network game
- Architecture diagram
Elements of a network game
Depending on wether you want your game to have web export to play in the browser or you want to distribute installers for different operating systems you could opt only for a socket server or also have your own site. Having your own site is useful in general as it showcases your game and you could still distribute installers through there if they are free or just go with one of the digital stores like itch.io or steam.
In any of the cases you would need a central web server. This central web server will need a socket connection (TCP/UDP) where clients will connect for various services. The central web server will be responsible to keep track of the players, handle connections, register new users, handle matchmaking, handle logins, etc.
If you go with adding your own HTTP site – you can use some web framework to create a few pages for registering users and accessing your web game. Then you can go with Godot’s web export for example and serve the game as one of the web pages.
The socket connection on the central web server is a connection only suited for game clients. The UI that users can access it with should be secured and only accessible through the application you provide. There are several methods of securing that connection as you don’t want thousands of requests to be able to slow it down.
The server pool is a good separation. It can physically be the same machine with the web server but being separated allows for expanding it in the future. You will be able to also make containers for running a game instance that will be registered in that pool of machines. Every game instance will also register itself with the central web server so that the central server knows how many game rooms it has available for matchmaking.
Database is simple enough. It will contain the users, history of games and other much needed data. The clients will only ever be able to communicate data trough the central web server’s API and so do the pool of game instances. This will provide a nice separation and security overall. Same as the instance pool the database can be on the same machine but can also be completely separate.
As I described the elements of your network architecture you can see them visualized in this diagram. In short I will describe the flow of actions that the users may take and what should happen behind each of them.
Next the user starts the game where he/she should connect and authenticate with the socket connection. In the web you can opt-in for a WebSocket (TCP) or WebRTC (UDP) connection. The authentication could include username and password or some kind of token that the HTTP API already provided. Before the user can be authenticated though you might want to secure the socket with some kind of a validation secret that only your game client can provide so that you close connections coming from other programs.
After the client is authenticated he should effectively be inside of your game’s hub. Options like chatting should be available. The central server should now provide all kinds of persistent information for your user that is saved accross games.
From here user can enter matchmaking. If he/she requests matchmaking the central server should put him/her in a queue to wait for enough users to join a game room. After that is ready the central server should pick up a game instance from its pool of game rooms. The picked room is sent over to the players and information is given to the room to prepair and wait for those users. You can use a simple token or ticket sistem that will act as a pass for the room to allow the given player to connect.
Game rooms should also usually communicate over a socket like WebSocket or WebRTC. The game instance is responsible then for playing out the game and synchronizing the game state with all participants. Participants should only send input to the game room and the room should calculate and synchronize the real state with the clients. Clients will also calculate the state of the game and not wait for the room to give them the real positions. Here you should have some lag strategy of course as game clients will always recieve outdated information from the web server.
After a game is conluded the clients should be returned to the main hub/server. The room instance may report the game results to the server so that the server saves it in its game history. The room should reset state and register itself to the pool as available once more.
The database is a data structure where you save all kinds of information about players or game history. It is best if this database is only accessed through one place (the central web server) but you may opt-in to be able to access it from each game room instance. The central server access could also provide a way (API) for the room instances to access certain data.
Http and Socket connections
HTTP connections should only be used for the website portion of things. You could have a website to register or login players. You could also completely skip that and put all of this into your game client when communicating through a socket. It’s completely your choice here and based on your expertise with web development.
Socket connections should typically be UDP for the game part of things where performance is required but accuracy of data is not. By accuracy I mean that data could be lost on its way to the server or other clients. Certain game actions are important to be transmitted absolutely accurately so you could use secure transmitions even over UDP.
There are also TCP type sockets. HTTP is a TCP connection. The other major TCP socket connection is WebSockets if you want to develop your game as a browser client. WebRTC is not so mature so you may in general opt-in for TCP. TCP is a secure protocol meaning data will be re-transmitted and always read in order it was meant to. This may have performance implications but it is up to you or your needs what type of connection you will develop in mind.
Authentication & Security
Website frameworks exist for most languages where authentication is provided out of the box. I will not delve deep into this topic. Just don’t store plain text passwords in your database.
The most authentication and security should come in the form of limiting what can connect to your sockets. The simplest is for your client to have some kind of a secret challenge that it recieves from the central server where the calculation between client and server should match. Every client then recieves different input for the calculation. Your authorized clients should have no problems in solving this challenge. Every other connection should be closed.
The other major point is protecting information during a game room and stopping any cheating behavior. You should be careful there what data you transmit especially where limited visibility like fog of war is present. The general rule of thumb is to transmit input (from keyboard and gamepads) from the clients and the room to decide what to do with this input and then transmit back the result. To achieve this without too much lag you could still leave clients to do their own calculations and then sync up with the results when the server provides them.
Separate game instance pools
These are separate as to not load the central server too much. If you have a game with a limited number of people this will be your approach. Examples with game rooms could be games like Among Us, Fortnite, League of Legends, Dota 2, World of Tanks, etc. They seperate a few people into their own game and then return them back to the hub. You might also use this approach if your world is dividable on regions.
Each room will be a client instance of the game that connects up to the hub and authenticates in some way as a room. You could even allow your users to create their own server connections this way if they want to play with their friends in a non-secure game by providing them with a dedicated server app. Some games provide such dedicated servers like Counter Strike or Minecraft. Keep in mind that the results from such games cannot be considered official as the dedicated server can be tampered with and reverse engineered (cheating).
A room will receive a signal from the matchmaking on the central server when players are going to connect, which players to expect and to prepare the game. Then the room should initialize its state for the game and then after the game is over reset it back to normal.
Godot provides some feature toggles for exporting your games so you can select a different game scene or even different code to be evaluated or even exported for the clients that players use and the game client that the room instance will use. They should still be able to communicate through common functions and to be able to have the same state when all calculations sync up.
In this article I gave a very high level overview of what a game server should look like for a MMO game. I did talk more or less for a game that is played in the browser but realtime with other players because that is one of the harder cases of implementation. This is also what I will show in later tutorials on this topic.