PDA

View Full Version : Synchronizing Clients with Server



technomage
05-02-2005, 10:10 PM
Hi everyone,

I'm trying to implement a simple client/server application which will allow an Open Dymanic Engine simulation to run the same on all the client machines as it does on the server.

In order to do this I need to ensure that the clients are calling the API call to advance the simulation state at the same time, in other words I need to make sure that the clients and server are in sync.

Does anyone have any hints on how to start this sync? I know I need to take into account the transmition time between the server and the client (I'll be using UDP to ensure this is as low as possible), but my brain keeps blacking out when I try to think about the process I would need to go through. :wink:

One possible solution which I can up with was to send a number of small packets to determin the lag on the network (in msec) and once this was found I could send the server time and figure out exactly how much time would need to be added to the locatime to ensure the times are the same. But I;m not sure if using the sysmte clock wold get accurate enough. Shoud I be relying on the ticks passed since the app started?

Any thought's would be welcome.

Dean

Huehnerschaender
05-02-2005, 11:55 PM
Hi there,

In my opinion you will never get the clients running exactly the same time as the server does. And I don't see the need to run all PCs exactly the same tick.

The server can not send sync packets to many clients the same time and you can not assure that all packets have the same delivery time. It's like a highway where the cars are the data-packets. Not all cars can reach their destination the same time (ok, we're talking about nanoseconds here :wink: )

So all you could do is something like that:

- start server application
- spread start message to all clients
- do your thing

If the start message is spread and every client has got it, this is the time where the clients should start working. Because otherwise the first client would start while other clients are still waiting for the start message.

So I would do it like this:

As you said before, try to find a good time value for delivery of the packet.
Then send the start message (I would send a delaytime in the packet) to each client and the delay time should decrease with each client.

for i := AmountOfClients downto 1 do
SendStartMessage(Delaytime * i, ClientIP[i], ClientPort);

Something like this...

By the way, the UDP-protocol has no guaranteed delivery implemented. So what do you do if packets do not reach their destination? Put a thought on using another protocol.

Regards,
Dirk

Paulius
06-02-2005, 09:24 AM
If it is for a game you should do guessing physics, run the simulations separately on all machines, but when information about positions, rotation, etc. is received from the server update to that.

{MSX}
06-02-2005, 05:43 PM
In fact, you cannot keep them completely syncronized. You cannot hope to run the WorldUpdate function simultaneously.

A things to keep in mind is that server should be the "official copy" of the game, while the clients are a kind of "best effort copy", where slight errors can be present.
So the server is responsible to decide collisions and events in general of the game. For example, it can happends that in a client, little errors can result on a collision (for example a missile hitting the target), while in the other clients and in the server this doesn't happend (the missile miss the target). In this case you get a de-syncronization (or whatever it calls :P)
A way to handle this is to remove all controls and events from the clients and let the server do the calculation and notify clients of happening of events in the game.
The client should simply obey to server notification and try to correct delays if it can. For example, the server can put in the notification, information about position and orientation of the interested objects. In this way, the clients, when receive the notification, can also do some adjustment .

This is a little more problematic in ODE becouse of some things:
- sending the object information on collisions means to send the position, orientation, linear velocity, angular velocity, etc etc..
- correction are difficoult to apply. ODE is made to work naturally by itself, if you "hard move" the objects by changing the position manually, it can take it bad.. :)

About the protocol, i think you should use UDP. It is more quick and the problem of loosing packets is very limited. The fact that it is not granted that the packets arrive, doesn't mean it will loose many of them. In my life i've never seen and UDP packet being lost while i used them in my games.
Anyway, for the "control communications", you should use a normal TCP connection. It's far more easy for that job. You should use for client and server initialization, and to send the "start" message. Then you switch to UDP until the end of the game.
Don't warry about the delay of the "start" message. That for cycle you've written that handle the delay is useless IMHO. It's not a single packet that causes problems, and the starting delay is adjusted as soon as the first packets start to travel to and forth.

Let me know how you do it and how it comes out since i'm interested in it.. i'd like to add multiplayer support to FunkyCars.

Bye!

technomage
06-02-2005, 10:17 PM
Thanks for the feedback all of you.

I've decided to take on a slightly different approach to this. The server will hold the complete simulation and inform the clients of changes to any object this isn't directly "owned" by the client (unless a collision occurs). The client will be responsible for handling it's own physics and will therefore update it's own position, lin vel and ang vel etc to the server.

So in a two player system the player who is the server will have two worlds one for the player object and one for the whole world, remote players will have one world. This might seem unfair but the extra processing a server client will have to do might make up for the lack of any lag on the network :wink: It should also linit the number of ODE objects the would need manual updates.

I had already implemented a rather interesting comms system. The client connects via TCP and the server then sends all messages via UDP socket to a specific port on the client. (the client has already opened a specific upd port) unless it's flagged as urgent in which case it used TCP. All client messages are sent via TCP to ensure they make it. I haven't done any serious load testing on this but it seems to work nicely.

I've had a look around on www.gamedev.net and there are a few articles on "dead reckoning" that seemed useful. I'll hopefully be able to share some of my insights in my "Network Programming using SDL Net" series at some point in the future, so watch this space :D

and thanks again for the feedback.