Clock Synchronization of Client Programs
IntroductionMultiplayer games often need to deal with the complex nature of the networking technology. Most notably, multiplayer games on Internet represent a greater challenge to the developers than those games written only to run on LAN environment. One of these challenges is the delay that exists from the time at which a process sends a message over the network to the moment at which the message is received by the other process. This delay is known as network latency, it’s both a consequence of our world’s physic constraints and the design of the networking technology (protocols). Network latency, informally known as LAG, represents a serious challenge to multiplayer game developers. The LAG can have disastrous effects on the player’s gaming experience, making the game unplayable. The latency can change over the course of a game session, this dynamic behavior of the network requires a solution that can detect this changes and react to minimize their impact in the game. Client clock synchronization is a simple technique that can be used to cope with network latency. It’s not a magic solution but in some specific cases can greatly improve the experience of the users, masking the effects of network latency and making the game look pleasant and fair. The present document describes how to synchronize client clocks over the network. The first part of the document describes how the messages are encoded before sending them over the network. The closing part of the document describes the messages that the clients and the server exchange in order to synchronize the clocks. Game scenarioRemember that our goal is that the game can react to the network’s dynamic behavior. For this purpose we are going to suppose that we are working on a simple arcade multiplayer game in which two players compete. The programs’ clocks are the main and only synchronization mechanism in which we are going to be relying on to achieve our goal. A clock is just a simple counter ranging from 0 up to N, the current value of a clock represent the number of milliseconds that have elapsed since the game began. It’s essential that when a game session starts, that is when the game itself begins, all the three clocks (two clients and server) be synchronized and have the initial value set to zero. The algorithm described later on this article will let us do this. Once the clocks are synchronized we can use them for at least three very important functions:
class VClock {
DWORD mRealStart;
bool mStarted;
public:
VClock() : mRealStart(0) {} ;
bool Started() const { return mStarted ; }
void Start( DWORD time_delta )
{
mRealStart=GetTickCount()-time_delta;
mStarted=true;
}
DWORD getTime( ) const
{
assert(mStarted) ;
return GetTickCount() - mRealStart;
}
};
The function GetTickCount retrieves the number of milliseconds that have elapsed since the computer was turned on. The value returned has 8 bytes long and the biggest value can be 49.7 days, which is more than enough for a game session! Otherwise the player is in grave danger and needs to get help.
The real clock is the value returned from the |
|