Network Game Programming - Issue 07 - I bent my Wookie... by Dan Royer (25 August 1999) |
Return to The Archives |
Introduction
|
Right, this week's topics include synchronization between client(s) and server; optimizations, tips and pitfalls to avoid; links to sites that can provide you with some more information on network and network game programming. |
Synchronization
|
Synchronization is extremely important because it makes sure that what you are seeing on your screen is the same thing as everybody else which means that if you shoot someone with a missile they're actually there to get hit. At first this problem seems really easy to solve: make the server keep a copy of everything going on in the game and have the server update players as necessary. This also prevents players from most forms of cheating, depending on how you design your messages (more on that later). As I said, at first the problem seems pretty straightforward. Here is where lag becomes your mortal enemy. Consider this picture: At time t1 the local client (you) start to move forward. The message is sent through the network and a little latter (at time t2) it arrives at the server. At this point the server copy starts moving forward. Unfortunately it is already behind the actual position because it was late getting the message and always will be. Now the server broadcasts to all clients that you have started moving forward. Every client, including you, receives the message. Effect: all clients are now behind the SERVER. Worse still, your ship tried to compensate for the difference between the server message and your current state by "jumping" your ship to where the server said it should be. So what happens is you see everyone else's ships at a slightly old position, plus your player's movements are jerky and confusing. The solution comes in two parts. |
Prediction
|
We know where the ship is at t0. We know that any message we send to the server won't arrive until t1. So what if we take the data from t0 and predict where eevrything will be at t1 and draw that to the screen? Now the user sees almost exactly what will be happening on the server when the next client messages get there, instead of always responding a little too late. The second part of the solution is to figure out how long the t1-t0 delay really is. You could set up a ping system to hit the server every snapshot or two but I have a better idea. When the player successfully logs in the server should send it the current snapshot ID number. When the client sends out data to the server it should be earmarked "intended for snapshot S(n+i)" and when the server sends out snapshots it should send "This is snapshot n, the last data I got from you was intended for snapshot x". i here is equal to (int)( ( t1 - t0 ) / ( milliseconds / snapshot ) ) (So if you were sending out 20 snapshots a second you would have (int)( ( t1 - t0 ) / 50 ). x is some previous n+i. Now given that we know when we sent message intended for n+i and we know what time we got an acknowledgement from server that gives us the ping value! Average that over a could of snapshots and things should run pretty smoothly. (I guarantee you that a TCP/IP system will have greater t1-t0 delays than a UDP system.) |
Extrapolation
|
Now we're only sending out snapshots every couple of milliseconds, so in order to keep things moving slowly the client and server also have to make a guess at what goes on between messages. Given that you know what everybody is doing at a particular instant in time and what they are doing to cause change at that instant you can extrapolate where they will be in the next little while. This is close to but not quite the same as prediction because can go beyond time t1 and sometimes has to in order to keep the game running smoothly. If you watch Quake III's lag-o-meter there are blue and yellow lines being updated every frame. the blue lines mean extrapolation is occuring at less than t1 (which is fairly safe) and the yellow lines mean extrapolation is going beyond t1 (which becomes less and less acurate). |
TCP vs. UDP (continued)
|
TCP is a simple and effective way of transmitting data. For making sure that your client and server can talk to each other it is very good. However, it carries with it a lot of overhead and extra network lag so once you feel you are ready you should make the jump to UDP. The big problems you will face with UDP include:
While switching to UDP will get you a signifigant speed boost, there are a few more tricks you can try. |
Optimizations / Tips
|
|
Things not covered by this article
|
|
Links to other resources
|
http://www.parsec.org/netdocs/index.html www.parsec.org has put together an excellent little paper on how they designed their network API. It even covers slot servers and master servers, so if you don't find what you're looking for in this article, it'll definitely be there. http://www.sockets.com Lots of helpful material on windows sockets programming |
Source Code
|
Yes, as promised, there is source code. You may have seen the game displayed as a screenshot of the day. However, I'm not releasing it until I've cleaned it up and add more comments/error catching routines. Any differences between what I said here and what I do in the code will be clearly spelled out in the accompanying readme.txt Download network.zip (163k) This is the end my only friends, the end... |