Network Design Question

Hey all, I have a design question about how to set up a feasible 8-player game using a client-server model. The game is very simple (a bomberman remake, actually). The only things the clients will be sending to each other are:

  • chat messages
  • change in X,Y sprite location
  • placing of a bomb at X,Y location
  • picking up of powerup at X,Y location
    and maybe a few more things, but that’s about it. all of the “events” could be represented by simple strings, since the client will do all of the message processing (if the client receives a message that says “NEW BOMB, player1, 4, 5”, it will create a new bomb object for player1 at location 4, 5. etc etc. So, keeping that in mind, will the following server model work?

the server would do the following:
– start server

– create thread that checks for new connections

– if new connection X, create 2 new threads to handle X: a receiveMessage thread and sendMessage thread

the two threads for each client would do the following:

the receiveMessage thread will continuously check for a new message over connectionX’s socket. If a message is recieved, the message is added onto the “toSend” queue of every other connection.

the sendMessage thread will continuously check the “toSend” queue to see if there are any items in it. If there are any items to send, it will remove an item and send it to the player. The “toSend” queue of each player will obviously be synchronized to protect it’s data.

My question is: will this model work? The only thing the server needs to do is receive updates from a client and foreward those updates to every other client connected to the server. The server itself doesn’t do any actual message processing.

Is there a more efficient / better way to set up a simple “data forewarding” server? I’m not -too- concerned about lag issues at the moment, just that it will work and every player will be relatively in-sync. And, on that note… how can I ensure that each of the clients IS in sync with all of the others?

Any input/ideas would be greatly appreciated :slight_smile:

As a simple system it should work ok. However:

  1. Text strings are quite ‘weighty’. you can be much more efficient, i.e. number the players as ‘1 to 8’ and when the game starts the server tells each client what the real name/colour etc. of clients are with the number. then messages just need to give a client number.

Similarly, each ‘action’ can be assigned a number, so ‘drop bomb’ is ‘0’ etc.

The whole message then becomes:
[action][clientID][any extra data required like X,Y]

  1. Syncing. Now theres the thing. If you use TCP, then all the messages WILL get through (eventually) so they should all stay in sync, although lag may be an issue.

However, you have the problem of timing. What if:
t = 0s: Player drops bomb next to player2
t = 1s: Player2 runs 1 step
t = 2s: Player2 runs 2 steps
t = 3s: bomb explodes

Now if everything was received with the right gaps, everything is ok. But as you are not sending the ‘bomb explodes’ as a message, then a client that receives only the first message will think player2 has been blown up (as the move messages were delayed).
Ways around this are:
a) Timestamping every action. Can get fiddly resolving if the player was actually blown up.
b) Send every state that happens (including explosions)
c) Run a server version of the game (more later…)

  1. Security: You may not care, but someone could easily hack the client to say ‘I have moved here’ where here could be some way away (auto-leap away from bombs) or in the worst case it could be an invalid position and cause every other client to crash!

The other approach is for the server to run the game, and send actions from the clients. The server updates the game, and sends the current state to each client. This avoids issues like the timing, as the server is the only part capable of deciding if a player is blown up or not. Security is simpler, as you just verify the commands off a client. If the command is illegal, you simply ignore it. It is hard to get the other clients to crash from this.

It all depends on what you need at the end of the day, but the main advantage with the server doing the work is a single definitive game state. For example - if all the clients get out of sync - which one is right?

Hope this helps,

  • Dom

Thanks for the reply Dom

You bring up some good points about the string sizes. I will definitely cut down the size of my packets to as small as possible :slight_smile:

As for syncing, that’s a good idea. I originally planned on only telling the clients to place the bomb, then having each client decide when it blows up (based on a timer in the bomb), and then who is near it / who dies. I was going to send player deaths to the server (if one client registers a player as dead, all will), however sending bomb explosions might be more feasible – I’ll have to try and see :slight_smile:

I agree that having the server control the game logic makes more sense, but I only have a month or so to complete this project. I think that making the server a simple packet-forewarding decide will make it easier on me. I’m not concerned about security issues for now, but you do bring up some really valid points that I will keep in mind for the future.

As for the client, how should I organize the sending and receiving of network messages in the main game loop? I’m assuming that I’d want to use as few threads in the client as possible. How few can I get away with? I was thinking about having one thread that constantly checks for messages from the server (this would be a blocking action), and updates a “fromServer” queue. Then, in the main game loop, I would process all messages (if any) in the “fromServer” queue, then process messages from the player. Finally, I would send all changes to the server and then update the screen.

Speaking of which… How should I set up the actual game loop in relation to sending messages to the server? Lets say I want to send 15 updates per second, but I want to render more than 15 frames per second. How would I do this so that I get good graphic performance, but don’t miss sending data to the server?

Ensuring you remain in sync has two main steps.
1: Maintain a fairly accurate network clock from the server (thuis is discussed in other threads in this section).

2: If you use TCP, you SHOULD usually stay mostly in sync.

The big problem is that when they go out of sync - who is right? this is the logic behind having the server running the definitive game state - a client can go out of sync but then the only problem is identifying this and requesting a new up-to-date gamestate off the server. This is usually done by creating a simple checksum of your state at a set time on the server, and when the client reaches that time by the network clock, it checks the checksum. If its different, it requests a new state. Be careful to allow a certain amount of allowable error or you end up requesting a full state every frame! this may be adaptable to just the clients, but you still have the issue of ‘who is right’.

One possibility is to have a client responsible for its own character, and the state checksums to be sent by the clients to refer only to ‘this characters state’. if a client has different, it requests a new state from that client only, but this system is easy to hack - I just code my client so I cannot die and hey-presto I am invulnerable.

As for the whole threading point, ty far the easiest approach is to use non-blocking IO. During an update you :

a) See if any messages are received. Handle these if they are.

b) Do game logic & generate outgoing messages

c) Send outgoing & loop.

No extra threads needed.
The same goes for the server, although having logging in on a different thread may be advantageous (although I don’t bother in my apps).

Using TCP will save you many issues (duplicated packets, delayed packets etc.). If you used UDP there are a whole host of things you have to watch out for :slight_smile:

so along those lines, using NIO, server should loop thru all clients and send datapacket out each channel?