views:

176

answers:

3

When I was writing a simple server for a simple client <> server multiplayer game, I thought of the following text-based protocol using a translation library. Basically, each command had a certain meaning, eg:

1 = character starts turning right
2 = character starts turning left
3 = character stops turning
4 = character starts moving forward
5 = character stops moving
6 = character teleports to x, y

So, the client would simply broadcast the following to inform that the player is now moving forward and turning right:

4
1

Or, to teleport to 100x200:

6#100#200

Where # is the parameter delimiter.

The socket connection would be connected to the player identifier, so that no identifier has to be broadcasted with the protocol to know what player the message belongs to.

Of course all data would be validated server side, but that is a different subject.

Now, this seems pretty efficient to me, only 2 bytes to inform the server that I am moving forward and turning right.

However, most "professional" code snippets I saw seemed to be sending objects or xml commands. This seems to require a lot more server resources to me, doesn't it?

Is my unexperienced logic of why my text based protocol would be efficient flawed? Or what is the recommended protocol for real-time action multiplayer games?

I want to setup a protocol that is as efficient as possible, because I do not want to use multiple clusters/servers to cover excessive amounts of bandwidth for my 2D multiplayer game, and to safe synchronization problems and hassle.

+3  A: 

You need to be aware of the latency involved in sending your data. "Start turning"/"stop turning" will be less effective if the time between the receipt of those packets is different than the time between sending them.

I can't speak for all games, but when I've worked on this sort of code we'd send orientation and position information across the wire. That way the receiver could do smoothing and extrapolation (figure out where the object should be "now" based on data that I have that is already known to be old). Different games will want to send different data, but generally speaking you will need to figure out how to make the receiver's display of the data match the sender's, so you'll need to send data that is resilient in the face of networking problems.

Also, many games use UDP for this sort of data transfer instead of TCP. UDP is unreliable, so you may not get all of your packets. That means that "stop moving now" or "start moving now" may not be received in pairs. When coding on top of UDP then it's even more important to send "this is the state right now" every so often so that clients get ample opportunity to sync up.

dash-tom-bang
I just gave an example though, a position state could be given with my "system" too. Eg 1#x#y would inform the client what a players real position is, so that it could correct the display (smoothly). My question is whether a text based protocol with a translation library is more efficient than other methods.
Tom
My point was that you generally don't want to deal in transition states. Text or not- doesn't really matter if you're not sending a lot of data, but each character takes up a whole byte regardless of the fact that you're presumably not using the whole range of values. So it is rather wasteful of memory in honesty, but if it works for what you're doing I wouldn't worry about it. Parsing text data is also pretty slow, compared to just reading bytes off of the wire and using them without anything beyond endianness translation. Text is certainly going to be easier to debug, though!
dash-tom-bang
I am going to completely restart my project, from scratch. I do need a more definitive answer, for example why people are sending serialized objects and how, what the advantage is compared to text. Or maybe I should send commands in binary as bitc pointed out?
Tom
Well if you've got something that works, there's no need to throw it all away!
dash-tom-bang
I don't, not for the amount of people I want to have online simultaneousely ;)
Tom
ok- then you're going to want to send your data as "raw" data. I.e. instead of sending text for "100", send the bits that represent that. Keep in mind network byte ordering, too, especially if you want to support heterogenous platforms.
dash-tom-bang
+1 reading this post, I had an illumination for a somewhat related problem
Lo'oris
What kind of protocol are you using Lo'oris?
Tom
+2  A: 

The common way is to use a binary format, not text, not xml. So with only one byte you can represent one of 256 different commands.

Also use UDP and not TCP. The game will be a lot more responsive with UDP in case of packet loss. In case of packet loss you can still extrapolate the movements. With each packet send a packet number so that the server knows when the command was sent.

I highly recommend that you download the Quake source code where you can learn more about network programming in modern multiplayer games. It's really easy to read and understand.

edit:

I almost forgot.. Google's Protocol Buffers can be of great help when sending complex data structures.

bitc
How would you send 256 commands in 1 byte? Some pseudocode would be highly appreciated. If I use UDP, can I replicate TCP's feature to resend failed packages? With your binary format, you still use a translation library as I am with my text format, right?
Tom
@Tom: I was terribly unclear. One byte can represent 256 different commands. So you can send one of 256 per byte. And yes, with UDP you can, by including a packet number, replicate a desired feature of TCP (getting data in correct order). Packet loss may happen anytime. With TCP you get very high latency. With UDP you can sometimes get less latency but lost information instead, which is usually good compromise in real-time online games.
bitc
+1  A: 

However, most "professional" code snippets I saw seemed to be sending objects or xml commands. This seems to require a lot more server resources to me, doesn't it?

Is my unexperienced logic of why my text based protocol would be efficient flawed? Or what is the recommended protocol for real-time action multiplayer games?

Plain text is more expensive to send than a binary format containing the same information. For example, if you only send 1 byte, you can only send 10 different commands, digits 0 to 9. A binary format can send as many different commands as there are different values you can fit into a byte, ie. 256.

As such, although you are thinking of objects as being large, in actual fact they are almost always smaller than the plain text representation of that same object. Often they are as small as is possible without compression (and you can always add compression anyway).

The benefits of a plain text format are that they are easy to debug and understand. Unfortunately you lose those benefits if you put your own encoding in there (eg. reducing commands down to single digits instead of readable names). The downside is that the format is bigger, and that you have to write your own parser. XML formats eliminate the second problem, but they can't compete with a binary format for pure efficiency.

You are probably overthinking this issue at this stage, however. If you're only sending information about events such as the commands you mention above, bandwidth will not be a concern. It's broadcasting information about the game state that can get expensive - but even that can be mitigated by being careful who you send it to, and how frequently. I would recommend working with whatever format is easiest for now, as this will be the least of your problems. Just make sure that your code is always in a state where you can change the message writing and reading routines later if you need.

Kylotan
I often get the suggestion to start with whatever I got at the moment and change it later. I have actually completely restarted my project and before I start writing code this time I'm going to document every subject I need to know things about, in this case it's what protocol to use for my networking. It seems like a binary format is the most efficient, so that really is what I want. I am not experienced with sending raw binary data though, could you maybe give me an example in java, actionscript or even pseudocode? That'll finish this chapter in my quest and allow me to accept your answer.
Tom
I'm afraid I am not proficient enough with Java or Actionscript to provide pseudocode. The java.io.DataOutput interface is close to what we're talking about, however. And in Javascript and Actionscript I believe you can convert a byte value to a one-character string via fromCharCode, I believe.
Kylotan
Could you give an example of a 1 byte binary command though? I've no idea how to do this.
Tom
You'd have to find someone with more experience of those languages to give you the specifics.
Kylotan