Monday, January 5, 2015

Mixing TCP and UDP to reduce latency in real-time connections.


Let’s start to use our best cards to deal with latency issues. Remember that previously (last entry) we chose to implement all dialogs between client and server based on TCP protocol. We also deactivated Nagle’s, algorithms among other strategies, that caused our app to experience high latencies.

      We have to make a step forward.

TCP packet delivery control adds  extra unknown sized traffic between client and server that we will pay with lack of gameplay. Every packet has to be acknowledged by the receiver and, in case of data lost, a new packet will be send with its consequent acknowledge. It's easy to understand  how this data interchange can impact in our mission to be fast.

So, let’s think about what kind of traffic we are sending  between client and server?. Can we tolerate some packet lost?. 

Basically, analyzing almost every game,  we have two kind of commands:
1.     The Commands that exchange client and server in order to configurate how the game will be (and prepare it before it starts) must be synchonized. We have to assure that we respect the order sequence described in our interface contract between client and server (see last entry). For example, We can’t pay a drink if we have not already ordered. At this time, the game has not began and it’s not critical if we experience additional delayed milliseconds. So we can and should keep using tcp protocol to implementing these commands. We can fully enjoy TCP packet deliver control since it doesn’t matter at all some little delay.

2.     The Commands inside a game need to be quick. It would seems quite obviously but once inside a game every millisecond saved worths a penny. We will be dealing with ticks about half a second because noone would play our game if we see our snake moving fast as a truck. We have to squeeze our brain to get this part of the game as fast as possible keeping on mind that we are playing across internet. This means different lag from players, changing player latency  during the game and  Players leaving the game once started.

Gathering these premises, it seems clear that we need to keep under control what we really send throught the net. So, we  have to avoid sending extra packets as our main objective… and which protocol is sending extra packets out of our control? TCP.
We need to avoid tcp acknowledge traffic that is generated by TCP deliver control packet. By doing this, we will reduce some data traffic but we will loose also the guarantee that packets are going to arrive at time and at the order that we sent from the other point.
In other words, we are going to use UDP wherever we can and add some extra functionality to guarantee order and delivery issues that we need during the game.

Focusing on those commands related to the game itself there are two kind of subcommands:

1. List of movements consolidated by the server:

Keep on mind that the server is imperative and is in charge of guarantee that every client has the same view of the game. So, we decided to send, once every tick ends, a message containing all the movements consolidated by the server. With this message, the remote client will move non own players and will check if his anticipated movement can be confirmed. If we are lucky, everything is ok but if the remote client movement does not arrive or arrive to the server once the tick is ended we may be in troubles. In fact, we will face with remote/server inconsistencies if the remote client has changed the movement direction because the server won’t realize and the server will have sent back a movement with no change direction.  This means that the remote client will be forced to move back to the last tick scenario and move again based on server moments.

This means that we have to implement some movement buffer mechanism to allow this movement back described above. It also  means that we have no alternative except keep using TCP protocol. This messages has to arrive to the remote clients  sorted and every tick (we can allow certain delay). Otherwise, we would have to implement packet delivery control because it matters the order of list of movements and specially because it would make by far more complex  the implementation of the movement back algorithm. Let’s think how would we do if we can't assure that every tick will receive a confirmation of our predictions.

Yes, you may think, let's send the whole game board every tick. This means more and more data to send and that is one of rules that we can’t break .In fact, remember that we move non own players once list of movements are read by the client. So, the worst thing we can expect is some addicional lag between own player and other remote players.

2. Movement command that the client sends to the server:

Maybe the most important command that we need to be quick is the movement sent by the client to the server. It have to arrive before the server closes the turn tick. So, every movement received later is discarded and it will be used current direction to make the player server movement. This, as describes before,  will produce an ammendment to the remote client that is late once he gets the summarized message sent by the server. This discard issue it’s pretty the same as loosing  a client movement message. So we can use the same strategy.

The main idea is that a
 client message late can be considered as a client message lost. So we don’t care at all if it’s acknowledged by the server. We only want to arrive early. The acknowledge is implicit by the consolidated server movements that the server will send once the tick ends. So, we got it. We have made our custom delivery control message and this means that we don’t need and we don’t want TCP Protocol.

Let’s use UDP protocol for this commands. By doing this, clients are going to arrive sooner so it means that less movements are going to be rejected. This will allow us to reduce server tick time and we will get a faster game!!! In the other hand, we will loose some packets but we  will reduce at the minimum expression the lag between client and server that’s is our main goal.


So summarizing, we finally will use a
 mixed combinations of protocols to keep our net dialogue coherent and a fluid online game with little gap between server and client.

No comments:

Post a Comment