Question

I have a general question about programming the client/server communication on a network game. I use TCP as protocol, and the communication ... works, but I'm not sure, if it is a efficient way.

In general , actions that happen on the client-side will go throught all this steps:

  1. Some action (eg. a Fireball is cast)
  2. [*]For this action i defined a string (eg. #F#270#130#, which means the 'F' says it's a fireball and 270 is (for example) the degree of the angle, 130 - the speed of the fireball that is shoot.)
  3. String goes into outputpuffer of Client & waitingqueue
  4. String is sent
  5. String is received by server
  6. [*] Server needs a lineinterpreter that can detect the meaning of the string (here : what means F? It is a fireball!) & adds a unique identity, based on, from which client the command was received.
  7. [*]The Server needs to calculate logic, based on the action happened (fireball does damage to someone, does it hit someone (immediately) or does it just fly first?)
  8. Server sends an (updated) string of the action(s) that occur to all clients. (eg. maybe the fireball is slowed down in speed for some reason - here will be an updated string (#F#12345#270#90# - 12345 is the unique player identity)
  9. clients receive string
  10. [*] clients resolve string to a command + handle it (fire an animationsequence...)
  11. client that originaly sent the command compares received string with string in waitingqueue - when equal, do nothing (to smoothe out some action, otherwise through connection problems /delay, some action would occur twice or jump from location to location, based on ping

Is it really necessary to go through all these steps? At all steps marked with [*] i need to define new lineinterpreters/action for each command, so i'm coding each action twice, client & server-side. I read something about sending serializable objects, but in genereal the idea seems to be the same to me, i send an object, that has to be interpreted+handled and i send an object back...

Any hints? To solve the whole communication more elegant, with less coding ? Or a bit more sorted - all these #F# #M# #H# tags for different actions are making it more and more complicated :)

(In fact i actually have the following handlers/actions:

-move -look/rotate -hpchange -firearrow -spawn/disconnect ...)

Hope you understand what I mean - I know, I could just continue coding like that, and it would work somehow, but it just seems too complicated as it could be.

Thanks!

Was it helpful?

Solution 2

You need to look at several factors before you decide if your game requires any changes.

Firstly, is TCP the best communication channel? Have you compared it to UDP. Would it be better to implement the networking using UDP? Would it matter if a few packets went missing? What happens if the network is slow?

Secondly, look at how often you are polling/pushing to the server. Can this be reduced? Does the game have to be in real-time. Do all parts of a game have to be in realtime. Perhaps certain things can be non-realtime. A fireball will continue in a straight path so you dont have to keep updating the server about its position, you can just tell it about its direction and speed. What other aspects of the game can be non real-time. The only thing that needs sending is, players locations and actions. Most other things like collision detection can be offloaded to the client.

Thirdly, does every keypress need to be sent to the server? If the user is against the wall and wants to move further, the client knows that they cannot and thus will not send those keypresses to the server. If the user has moved to a new valid location, then update the server. Can certain things be buffered and sent to the server in one go, instead of sending several queries to the server. i.e. if I move forward, jump and throw a fireball, thats 3 keypresses on the client side, can they be buffered and sent at the next 500th millisecond?

If you are worried about the networking overhead, you should be working at the bit level. Instead of sending a long string "#F#270#130#" - which is 11 bytes long, would it make sense to send 3 consecutive bytes (24 bits).

7 bits represent the action (127 different actions). 9 bits will represent the angle (1-512), but you only need it up to 0-360 degrees. 8 bits represent the force.

This or any other byte format is shorter and easier to use over the network, and produces tighter code. Also binary comparison is faster, so writing your action parser on the server is now made easier. I.e. instead of a large switch case looking for #F#, you just look at the first 7 bits and compare it to an int.

Can you reduce other networking overheads, instead of force being decided by the client, can the server decide this. i.e. a standard force, or 2 levels of force (much better as this can be represented by 1 bit). Which stops the client and malicious users sending rubbish data across to the server (like force of 999), now the force can either be a 0 or a 1, i.e. speed of 10 or 20, nothing silly.

OTHER TIPS

You could do it in a more OO way if you:

  1. Define an object called Action or something like that, which has all of the above parameters - type of action, direction of action (or target), damage dealt, etc..
  2. Create those Action objects as your game normally executes
  3. Use ObjectOutputStream chained to your TPC Socket to output the whole Action object to the server/ pass it back to the client.
  4. On the server, interpret what happens by examining the recieved object from ObjectInputStream.

I think this way would be cleaner and more flexible in case you add more logic, than just analyzing strings, but not as fast (since objects going into ObjectOutputStream need to be serialized).

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top