What every programmer needs to know about game networking
January 24, 2010
Introduction
You ' re a programmer. Have you ever wondered how multiplayer games work?
From the outside it seems magical:two or more players sharing a consistent experience across the network like they Ly exist together in the same virtual world. But as programmers we know the truth of what is actually going on underneath are quite different from what It turns out that it's all a illusion. A massive sleight-of-hand. What you perceive as a shared reality are only a approximation the unique to your own point of view and place.
Peer-to-peer lockstep
In the beginning games were networked peer-to-peer for each of computer exchanging with each of the other in a St AR topology. Can still this model alive today in RTS games, and interestingly for some reason, perhaps because it is the Way–it ' s still how most people this game networking works.
The basic idea was to abstract the game into a series of turns and a set of command messages when processed at the Beginnin g of each turn direct the evolution of the game state. For Example:move, attack, construct building. All then needed to network this is to run exactly the same set of commands and turns on each player ' s machine starting From a common initial state.
Of course this is a overly simplistic explanation and glosses over many subtle points, but it gets across the basic idea How to Networking for RTS games work. Can read more about this networking model here:1500 archers on a 28.8:network programming in the Age of Empires and Beyo nd.
It seems so simple and elegant, but unfortunately there are several limitations:
The IT ' s exceptionally difficult to ensure this a game is completely deterministic; That is each turn plays out identically in each machine. For example, one unit could take slightly a different path in two machines, arriving sooner to a battle and saving the day On one machine, while arriving later on the other and ERM. Not saving the day. Like a butterfly flapping it's wings and causing a hurricane on the other side to the world, one tiny difference i N Complete desynchronization over time.
The next limitation is this in order to ensure that the game plays out identically on all machines it are necessary to W Ait until all player's commands for this turn are received before simulating that turn. This means so each player in the game has latency equal to the most player. RTS games typically hide this by providing audio feedback immediately and/or playing cosmetic animation Y truly game affecting action may occur only after this delay has.
The final limitation occurs because of the way game synchronizes by sending just the command messages which the State. In the ' order ' to work it are necessary for all players to start the ' same initial state. Typically this means the player must join up in a lobby before commencing play, although it is technically possible To support late join, this isn't common due to the difficulty of capturing and transmitting a completely deterministic St Arting point in the middle of a live game.
Despite these limitations this model naturally suits RTS games and it still lives on the today in games like "Command and Conq Uer "," Age of Empires "and" StarCraft ". The reason being that into RTS games the game state consists of many thousands of units and are simply too to exchange Between players. These games have no choice but to exchange the commands which the drive the evolution.
But for other genres, the state of the art has moved. So that's it for the deterministic Peer-to-peer lockstep networking model. Now lets to the evolution of action games starting with Doom, Quake and unreal.
Client/server
In the era of action games, the limitations of Peer-to-peer lockstep became apparent in Doom, which despite playing-O Ver the LAN played terribly over the Internet for typical users:
Although it is possible to connect two DOOM machines together across the Internet using a modem link, the resulting game W Ill is slow, ranging from the unplayable (e.g. a 14.4Kbps PPP connection) to the marginally playable (e.g. a 28.8Kbps mode M running a compressed SLIP driver). Since These sorts of connections are the only marginal utility, this document'll focus is only on direct net connections. (faqs.org)
The problem of course is that Doom is designed for networking over LAN only, and used the Peer-to-peer lockstep model de Scribed previously for RTS games. Each turn player inputs (key presses etc.) were exchanged with other peers, and before the any player could simulate a frame a ll other player ' s key presses needed to be received.
In other words, before your could turn, move or shoot your had to the "wait for" inputs from the most modem player. Just imagine the wailing and gnashing of teeth that this would have resulted into for the sort of folks who wrote above "These sorts of connections are of marginal utility".
In order to move beyond the LAN and the "connected elite at university networks and large companies, it is necessary To change the model. And in 1996, which that ' s exactly what John Carmack did as he released Quake using Client/server instead of Peer-to-peer.
Now instead to each player running the same game code and communicating directly with each of the player is now a "C" Lient "and they all communicated with just one computer called the" server ". There is no longer any need for the game to is deterministic across all machines, because the game really The server. Each client effectively acted as a dumb terminal showing, the approximation as it game out on the server.
In a pure Client/server model run No game code locally, instead sending your inputs such as key presses, mouse movemen T, clicks to the server. In response the "Server updates" state of your character in the world and replies with a packet containing the state of Your character and other players near. All the client has to do are interpolate between these updates to provide the illusion of smooth movement and *bam* your hav E a networked client/server game.
This is a great step forward. The quality of the game experience now depended on the connection between the client and the server instead of the most LA Gged peer in the game. It also became possible for players to come the middle, and the number of game players as increased T/server reduced the bandwidth required on average per-player.
But there were still problems with the pure model:
While I can remember and justify all of my decisions about networking from DOOM through Quake, the bottom line are that I W As working with the wrong basic assumptions for doing a good internet game. My original design is targeted at < 200ms connection latencies. People that have a digital connection to the Internet through a good provider get a pretty good game experience. Unfortunately, 99% of the world gets in with a slip or PPP connection over a modem, often through a crappy overcrowded ISP . This gives 300+ Ms Latencies, minimum. Client. User ' s modem. ISP ' s modem. Server. ISP ' s modem. User ' s modem. Client. God, that sucks.
Ok, I made a bad call. I have a T1 to my house and so I just wasn ' t familliar with the PPP life. I ' m addressing it now.
The problem was of course latency.
What John did next when he released QuakeWorld would change the industry forever.
client-side Prediction
In the original Quake you felt the latency between your computer and the server. Press forward and you ' d wait however long it took for packets to travel to the server and back to your before you ' d actuall Y start moving. Press fire and you are same delay before shooting.
If you have ' ve played any modern FPS like Call of the Duty:modern Warfare, you are know this is no longer what. So how exactly does modern FPS games seem to remove the latency on your own actions in multiplayer?
This problem is historically solved in two parts. The "I" is client-side prediction of movement developed by John Carmack for QuakeWorld, and later incorporated as Part of Unreal ' s networking model by Tim Sweeney. The second part is latency compensation developed by Yahn in Bernier for Valve. In this section we'll focus on that a part–hiding the latency on player movement.
When writing about him plans for the soon to be released QuakeWorld, John Carmack said:
I am now allowing the client to guess at the results of the users movement until the authoritative response R comes through. This is a biiiig architectural change. The client now needs to know about solidity of objects, friction, gravity, etc. I am sad to be elegant client-as-terminal setup go away, but I am practical above.
The latency, the client runs more code than it previously did. It is no longer a dumb terminal sending inputs to the server and interpolating between. Instead It is able to predict the movement of your character locally and immediately into response to your input, running a Subset of the game code for your player character on the client machine.
Now as soon as your press forward, there is no wait for a round trips between client and Server–your character start Movin G forward right away.
The difficulty of this approach isn't in the prediction, for the prediction works just as normal game code Does–evolvin G The state of the game character forward in time according to the player ' s input. The difficulty is in applying the correction back from the server to resolve cases when the client and server disagree Abo UT where the player character should be and what it is doing.
Now, this is you might wonder. Hey, if you are running code on the client–why is not just make the client authoritative over their player character? The client could run the simulation code for their own character and simply tell the server where they are each time they Send a packet. The problem with this is, that if, each player, were able to simply tell the server ' here's my current position ' it would be Trivially easy to hack the client such this a cheater could instantly dodge the RPG about to hit them, or teleport Instan Tly behind you to shoot.
So in FPS games it's absolutely necessary that the "server is" the authoritative over the "state of" each player character, I N-spite of the fact that's the player is locally predicting the motion of their own to hide character. As Tim Sweeney writes in the Unreal Networking architecture: "The ' Server is".
This is where it gets interesting. If the client and the server disagree, the client must accept the update for the position from the server, but due to late Ncy between the client and server this correction are necessarily in the past. For example, if it takes 100ms out of client to server and 100ms back, then no server correction for the player character P Osition'll appear to being 200ms in the past, relative to the "time up" to which the client has predicted the their own.
If the client were to simply apply this server correction update verbatim, it would yank the client back in time such that The client would completely undo any client-side prediction. How do then to solve this while still allowing the client to predict ahead?
The solution is to keep a circular buffer of past character state and input for the local player on the client, then when The client receives a correction from the server, it I discards any buffered state older than the The server, and replays the state starting from the corrected state back to the present "predicted" time on the client US ing player inputs stored in the circular buffer. In effect the client invisibly "rewinds and Replays" The last N frames to local player character movement while holding th E Rest of the world fixed.
This is way the player appears to control their own character without any latency, and provided the client and server Ch Aracter Simulation Code is deterministic–giving exactly the same result for the same of on the client and inputs T is rarely corrected. It is as Tim Sweeney describes:
... the best of both worlds:in all cases, the server remains completely authoritative. Nearly all of the time, the client movement simulation exactly mirrors the client movement from the server, so the Client ' s position is seldom corrected. such as a player getting hit by a rocket, or bumping into a enemy, would the client ' s location need To be corrected.
In other words, the player ' s character be affected by something external to the local player ' input, which Cann OT possibly is predicted on the client, would the player ' s position need to be corrected. That and of course, if this player is attempting to cheat
further Reading
UDP vs. TCP
What is the best way to send data between machines? Do I use TCP sockets, UDP sockets or a mixture of both? In this article we explore this fundamental choice and decide on the best option for fast-paced action games.
Sending and receiving Packets
This article shows how to send and receive UDP packets using BSD sockets, giving your source code that works across MacOS X , Windows and Unix.
Virtual Connection over UDP
Learn to create your own virtual connection between two in top of UDP. How to detect connection, the filter out packets from the other machines and detect via disconnection.
Reliability and Flow control
Learn to implement your own reliability system in top of UDP using sequence numbers and ACKs. Also presented is a simple flow control system.
Debugging multiplayer Games
Explains the techniques used by professional game developers to debug multiplayer games.
Floating point Determinism
Are it possible to get exactly the same floating point result (down to the Bit-level) the all time a? How about across debug and release builds? Across different compilers? Different CPU architectures?