Using WebSocket Protocol for Real-time Applications

WebSocket is a protocol designed for full-duplex communication channels using the same TCP connection. In 2011 WebSocket protocol has been claimed by IETF as RFC 6455. WebSocket API has been standardized in Web IDL by the W3C.

WebSocket vs. HTTP

  • WebSocket protocol provides full-duplex communication between a server and client, whereas HTTP does not support this mode;
  • WebSocket protocol uses a single connection for a two-way communication, while HTTP requires the creation of a new connection for each new request;
  • WebSocket protocol requires less overhead data than HTTP, which adds overhead data as it broadcasts headers for each new request. WebSocket only broadcasts headers for initial acknowledgement during HTTP protocol change.

If a browser does not support WebSocket protocol, it may use long polling as a fallback. However, in this article we will refer to other ideas.

WebSocket Applications

WebSockets may be used for tracking and synchronization of all kinds. Common uses include:

  • instant messaging,
  • multiplayer games,
  • real-time tracking,
  • content streaming,
  • shared document editing,
  • real-time analytics,
  • and push notifications.

Library Overview

autobahn.ws

In addition to libraries for Python, C++, Android and Javascript, the Autobahn Project enables open-source implementations of network protocols like The Web Application Messaging Protocol (WAMP).

socket.io

Socket.IO provides two-way, event-based communication in real-time, supporting a browser and server (e.g., node.js) simultaneously.

ws

This WebSocket implementation is simple to use and up-to-date against RFC-6455. Many consider it the fastest WebSocket library for node.js.

Java EE

Java EE features a special API for the WebSocket protocol corresponding to JSR 356, which supports the creation of WebSocket applications.

WebSocket Example

In this post, you will observe the implementation of a real-time app using WebSocket.

The purpose of this app will be to track the coordinates of a device. Upon launch, it will execute the following steps:

  • it begins to track its coordinates via GPS,
  • when it updates the location, it sends the data to a server app in real-time,
  • it updates the view in the browser,
  • it enables you to view the position of the device on a map in the browser,
  • …..
  • PROFIT!

WebSocket Server App

The simplest solution is using node.js as a server and “ws” and “express framework” for libraries.

In this setup, the task for the WebSocket server is to gather updates of the Android device location and broadcast its position data to all connected listeners (for the convenience of all browser and Android devices).

One more task the app handles is to disconnect devices, allowing removing on the side of the client (browser).

To implement the proper server behavior, we must register the following event listeners (callbacks):

  • connection,
  • message,
  • open,
  • and close.

Once a client is connected, it receives the locations of all devices from the ‘location update.’

Click to show

// send all reported prevoiusly devices with their locations
for (var key in lastLocations) {
   if (lastLocations.hasOwnProperty(key)) {
       ws.send(composeUpdateMessage(key, lastLocations[key]));
   }
}

Once the message on the location update is received, it broadcasts the location to all other clients from the device. To accomplish this, we must first define the broadcast method.

Click to show

// define broadcast method = simply sends the message to all connected clients
wss.broadcast = function broadcast(data) {
   wss.clients.forEach(function each(client) {
       client.send(data);
   });
};
Click to show

// broadcast location to all connected clients
wss.broadcast(composeUpdateMessage(device, parsedMessage['location']));

When the connection between the device app and the server is closed, it broadcasts the message to notify all that the device is no longer available.

Click to show

// notify all the client about device disconnection
wss.broadcast(composeRemoveMessage(device));

Browser App

The browser app receives updates of the device location via JavaScript WebSocket and identifies the position on the map. Location reports will be displayed once the device is connected. When the device app closes, the location will disappear from the map.

The app uses Google Maps API to display the current positions of devices. To view an example, you can obtain your own Google Maps API key from Google by clicking here.

The embedded browser WebSocket implementation will be used. Listeners should be set to the following events:

  • onopen,
  • onclose,
  • onerror,
  • onmessage.

Next, logic for the server messages of the ‘remove’ and ‘update’ type should be added. In case of removal, remove the marker from the map. Otherwise, update the marker position or create a new one.

Click to show

connection.onmessage = function (e) {
   var data = JSON.parse(e.data);

   if (data['type'] == 'remove') {
       deviceManager.remove(data.device);
   } else {
       deviceManager.update(data['device'], data['location']);
   }

   // data received from the server
   console.log(e.data);
}

Android App

This app will send location updates to the server via JavaScript WebSocket. LocationServices API and Autobahn will be used for updating and communicating with WebSocket. When the app is active (onStart), it will begin receiving location updates and sending them to the server. When it is closed, it will disconnect and stop getting updates (onStop).

First, the app receives location updates from LocationServices and sends them to the server immediately via WebSocket. In addition, it adds a unique device ID. This makes it possible to distinguish between devices.

The WebSocket server uses a special service to communicate, called WebSocketService. This handles sending and receiving data from WebSocket using MyWebSocketHandler for receiving messages.

Click to show

private static final String TAG = "MyWebSocketHandler";

@Override
public void onOpen() {
   Log.e(TAG, "Status: Connected to socket");
}

@Override
public void onTextMessage(String payload) {
   Log.e(TAG, "Got echo: " + payload);
}

@Override
public void onClose(int code, String reason) {
   Log.e(TAG, "Connection lost.");
}

WebSocketService also listens to broadcasted messages, using Android local broadcast messages with a special intent.

In addition, a special service called LocationService checks the location updates and sends broadcasted messages with a text payload. It uses FusedLocationApi to obtain location from Google Play Services.

Click to show

// register listener for location updates
LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, this);

Once the location is known, the service sends a broadcasted message containing a JSON encoded text.

Click to show

// send location to WebSocketService
Intent i = new Intent(WebSocketService.ACTION_SEND);
i.putExtra(WebSocketService.EXTRA_MESSAGE, composeJsonBody());
broadcastManager.sendBroadcast(i);

They start and stop both services from the Activity.

Click to show

@Override
protected void onStart() {
   super.onStart();

   startService(new Intent(this, WebSocketService.class));
   startService(new Intent(this, LocationService.class));
}

@Override
protected void onStop() {
   stopService(new Intent(this, LocationService.class));
   stopService(new Intent(this, WebSocketService.class));

   super.onStop();
}

Notes

  • This created solution allows connecting all user-tracking devices in real-time.
  • JSON is used as a format for server-client communication.
  • It is possible to use secure WebSockets (WSS).

Yevgeniy, Android Developer at VisualCraft