vegUI.org home of the javascript based window manager and AJAX framework

AJAX Series: Tutorial #4 - When bandwidth is an issue

written by vegu on 30 Jan, 2007 11:59:18
When i was working on my browser-based mmorpg i had to decide on the way in which the server and client communicate.

The client being the browser based javascript app and the server being handled by PHP and mySQL.
At first i was using an iframe system that would execute javascript code that was built by the PHP scripts on the server side.

This turned out to be working fine but in-efficiently, plus the amount of data transfer was a lot, considering the game sent a requests every few seconds.

Then a friend pointed me to AJAX style development, which, needless to say turned out to be exactly what i needed. I still had to work out one issue though and that was deciding whether to stick to the XML protocol or design my own protocol for it. I decided to design my own protocol because XML, while convenient still was too much bandwidth usage for this project.

I decided to go with a 'bitmask' like protocol, where i had user interface operations and arguments separated by delimiters.

I would use ; to delimit the operation calls and | to delimit their arguments.

So a response by the server for my game could have looked something like this:


14|Playername;22|Playername|hello world;


So how would i process this string? First i would split the string by ; meaning i would get an array holding all operation calls as individual elements.

code: js
var ops = uiOP.split(';');

Assuming uiOP is a string holding the text above, the returned array would look like this:


ops = [
[0] : '14|Playername',
[1] : '22|Playername|hello world'
]


Then id let the script loop through all operation strings and execute them. Executing them means we need to split them again, this time using the '|' delimiter, so we can filter out eventual arguments.

code: js
var i;
for(i in ops) {

var op = ops[i].split('|');
execute(op);
}

The op variable in the above example is , again, an array that holds all parts of the operation call. The first element in the array is the operation id, the following elements are arguments that were submitted with the operation call.

So still working with our example string op could hold


op = [
[0] = '22',
[1] = 'Playername',
[2] = 'hello world'
];


Then i send the array to a function called execute. This function then handles the operation array accordingly. It does so by taking a look at the first element of the array and selects the proper action for it. For example, let's assume that 22 stands for 'print chat message' and we would like it to print a chat message to our imaginary chat box in our imaginary game.

code: js
function execute(op) {

/* make sure op is a valid array by checking if the first element exists */
if(typeof op[0] == 'undefined')
return;

/* then we use a switch statement to act accordingly to the operation id which is stored
in the first element. Note that i am using parseInt on the value, that is because
the value is still a string and we want to use numerics.
*/


switch(parseInt(op[0])) {

/* op id is 22, which means print chat message in our imaginary game */

case 22:

/* the first argument is the name of the player who sent the message */

var playerName = op[1];

/* the second argument is the message itself */

var msg = op[2];

/* now that we have the name and the message we can
* print to our imaginary chat box */


print_chat_message(playerName, msg);
break;
}
}

The advantage to handling server-client communication this way is that it is very compact, which means less bandwidth used, which means less money spent on data transfer and network upgrades. The disadvantage is that you need to document the protocol very well else it can become confusing once the project gets a little bigger.

For example you could use 'constants' to represent the operation ids instead of working with raw numbers.

code: js
var UIOP_CHAT_MESSAGE = 22;

code: js
function execute(op) {
...
case UIOP_CHAT_MESSAGE:
.. print chat message ..
break;
...
}

Doing it this way clears up the code some, and you dont need to memorize the numeric value of each operation id.

Related Posts


Your Comment

name:*
email-address:

Are you human?



Comments

No comments yet.