Real-Time Device To Device Networking In Xamarin


Technical Articles
Artem Veselovskyy
26 October 2015
9941

Network connectivity is a major feature of modern world apps no matter the platform you are using. Can we imagine our lives without applications like Skype, Viber, Facebook Messenger, etc.? In most cases the answer is “No”. Have you ever been curious about how these apps communicate, or what is even more important, let you communicate with your friends, colleagues or family?

If the answer is “Yes” then let’s not waist time anymore and get ourselves familiar with the technologies enabling us to live our digital lives.

There are different ways for the programs to communicate with the server. These are:

1) HTTP approach. We typically use this to navigate the internet space using our favorite web browser. And the majority of the network enabled apps use this method as well to communicate with their servers. However instead of HTML web page the app receives json or xml payload that contains raw data from the server. Even some messaging apps use HTTP for data transport.

2) TCP and UDP sockets. This is the base for all other data transfer approaches. Every app uses this on the lowest possible level. In most cases even without developer knowing this.

While most apps can get away with the first approach even for real-time or close to this communication there are situations when app needs every single bit of network performance. Multiplayer games are this kinds of apps.

So how does it work?

There is a server and there are clients. The server can be the client as well but for now let’s keep things simple with only a client and a server that does not have a client role. Let’s call these peers. Take a look at the scheme below:

Client peer establishes persistent connection to the server peer and uses this connection for bidirectional data transfer. To make it possible the server app instantiates the SocketListener object and binds to an IP address and a port and starts listening to that endpoint for any incoming connections. Due to the SocketListener.Accept() method is a blocking call it is better to have a separate thread for listening for incoming connections. The Accept() method returns a Socket instance with information on a client and adds it to connected clients list. Protocol negotiation might take place prior to adding a client to the list but for the sake of simplicity we will send and receive just strings. At this point the server app has two threads: the Main thread (UI thread) and the Listening thread. After adding the client to clients list the app spawns another thread to handle connected client, the ClientHandling thread. Server does this for each connected client. The more clients – the more threads. Both these thread types do pretty similar job. Basically those threads handle a simple infinite loop like

while (true) { // do the job }. 

However we all know that infinite threads are evil and we have to have some kind of loop exiting mechanics.

while (client.Connection.Connected && state == SocketServerState.Running)
{
var buffer = new byte[1024];        
       var count = host.Connection.Receive(buffer); // fill the byte buffer and return its
     // length        
       if (count == 0 || state == SocketServerState.Stopped)
       {
       	break;
       }        
       OnReceivedMessage(host, buffer); // raise event to the UI thread
}

The client does pretty much similar job

while (state == SocketClientState.Connected)
{
var buffer = new byte[1024];
var count = mainSocket.Receive(buffer);
if(count == 0 || state == SocketClientState.Disconnected)
{
break;
}
}

There’s one small catch concerning the server socket. To keep connection alive the client must send at least 1 byte to pulse a server, otherwise the server may just close the connection.

The main difference between this and any other approach built on top of sockets is that HTTP for example is a protocol built on top of TCP and follows HTTP standards. However socket is a mean to control the transfer over TCP. Another pitfall of HTTP is that even if it uses a TCP socket to establish connection and send/receive data, it closes the socket just after the data has been downloaded after the response has been received. This means that there are large allocation/collection and connect/disconnect footprints in case of frequent requests.

Source code on the Github.com


Previous
Previous
Part 2 - Real-Time Device To Device Networking in Xamarin
Next
Next
How to Promote a Mobile App (Startup)