Tag Archives: mmop

Adversities in client-server communication

Hi ..
I’m already a while without posting, but keep developing the game with great intensity. During that time, I did several things but the most important one was the server configuration. In my first version, all event processing player … oops, before explaining the server, I will talk a little about the ‘events’.

Events
Everything that occurs in the game will be considered an event. If the player clicks a position to move around the map, pathfinding calculates the route to your destination and pass this list to an executor of events (I’m calling AsyncConsumerEvents). The origin-destination path is composte various events WALKING, where each is responsible for moving a tile to another. Other examples of events would be: ATTACK, JUMP, DIE … 🙂

First version
Returning to the main issue: on my first experience, the events were fully processed at the client and the outcome of these events (repositioning and select the appropriate image of the player) were passed to the server. The update of the sprites on the map was made ​​by consulting all the sprites in each iteration to draw the screen.

I was naive … of course this would not work. One iteration of the drawing screen lasts 16 ms. This means that 16 in 16 ms I searched all changes of sprites on the server. In my home network, sending and searching this information occurred 12-13 ms, but when I put on the internet, the cost came to 190 ms. That is, each iteration of drawing the screen suffered a delay of 174 ms, causing a lot of lag in the game.

In this version I used TCP packets without encryption.

Second, third, fourth… version
After that I have read many, many papers in an attempt to capture best practices for game MMOG client-server communication. All pointed to hybrid solutions with TCP and UDP. I found very interesting cases: the game Outgun and the peer-to-peer of the game Age of Empires 2. Outgun used an adapted version of the UDP protocol called RUDP that was all the game logic on the server. Age of Empires 2 had the complete state of the players on each client and always applied a delay of 200 ms to move players to avoid any lag in communication.

From these studies I made several experiments, all frustrated. I tried to use: UDP with the same port; UDP with different ports; UDP with different processes for sending and receiving; UDP recording state database and returning by another UDP; UDP to send the player status and TCP to other information… well, all these tests gave me something between 150 to 200 ms of delay between sending and receiving.

The problem was that in all cases I kept the rule in which the client processes the information, sends the result of processing and search all the updates from the server. This logic could not be maintained.

My current experience
AsyncConsumerEvents: Now, I mofifiquei all the logic of communication. First, even for security, event processing can not be performed by the client prior to authorization by the server. Why? If a client is malicious he may cheat. Before executing an event, I just send a request to the server. This request is being sent over UDP (encrypted) and does not expect any confirmation. If the server does not authorize another client process (AsyncReceiverEvents) that receives events simply will not receive this event. Just for clarification, I called him AsyncConsumerEvents why he consumes the events performed by the player and then send them to the server.

AsyncReceiverEvents: this process is continuously sending TCP requests (no encryption – in this case need not) asking the server if there is any event of the players (including this player). If there is any event, the client runs.

This logic only works well because I am also applying a maximum delay of 200 ms (as in Age of Empires 2) for the execution of the events after the command of the players. As the transmission (over UDP) and receiving (for TCP) is being conducted around 180 ms, we have a few instances of lag in the game when the network is slow.

Details
Why sending the event (UDP) is encrypted and the return (for TCP) does not? As the UDP packet is encrypted will be very difficult (unless a malicious user has the private key player) else pretend to be the player or modify events this player. Send to a fake server event would be a problem. So is encrypted. You no longer receive events such concern. If by chance the customer get a false event, its next iteration seek a true event. The client application knows how to treat it without problems. The most that can happen is a lag in the progress of the affected client.

Talking about encryption
I used AES 128 to encrypt the data and the CRC 32 to checksum the payload of the UDP datagram. The secret key of AES will be exchanged at an early stage to login with public key cryptography and authentication server in a certificate authority (as in https). This initial part is not yet implemented.

Server details
Once I started testing the client-server communication, I created a home server. It was an old machine running Ubuntu (too old). I installed MySQL 5.6.15 (64 bits) and the latest version of NodeJS via apt. I did several tests on the local network and got to publish it on the internet with no-ip.com. Suddenly the server stopped! Some hardware bug occurred. I abandoned that server and decided to create it in the cloud. I created an Ubuntu instance on EC2 amazon AWS. In it are configured MySQL 6.5.19 and NodeJS. I’m still using an old version of MySQL because of the large amount of stored procedures already created that need to be tested. In the future I will update.

Well, it is. I’m still programming this last alternative and while tests are good. After I comment with you the performance of the final result.