Introduction to the HTML5 WebSockets API

Sandeep Panda
Sandeep Panda
Share

HTML5 has introduced many new interesting APIs, including WebSockets. WebSockets allow developers to create powerful real time applications by establishing socket connections between the browser and the server. In other words both the client and server can exchange data at any time because of a persistent connection. This tutorial explains how to use WebSockets to create real time web applications.

The Problem

In real time applications, the connection between server and client must be persistent. So, in order to create an illusion of server initiated transfer long polling is usually used. WebSockets solve this issue by establishing a persistent socket connection between the client and server. Once the connection is established, it remains open until the client or server wants to close it. It significantly reduces the burden on the server and is best suited for low latency applications.

Getting Started

Opening a WebSocket connection is fairly simple. You just need to call the WebSocket() constructor to create a connection.
var connection=new WebSocket("ws://localhost:8787",['soap','json']);
ws:
and wss: are the URL schemas for normal and secured WebSocket connections, respectively. The second parameter is used to define the sub protocol name which can be an array of strings or a string. However, the server will accept only one sub protocol. During the lifetime of the connection the browser will receive several events such as connection opened, message received and connection closed. To handle these events use the following code:
var connection=new WebSocket("ws://localhost:8787",'json');
connection.onopen = function () {
  connection.send('Hello, Server!!'); //send a message to server once connection is opened.
};
connection.onerror = function (error) {
  console.log('Error Logged: ' + error); //log errors
};
connection.onmessage = function (e) {
  console.log('Received From Server: ' + e.data); //log the received message
};
As soon as the connection is opened, the browser sends a message to the server using connection.send(). If an error is encountered, the above code simply logs it. If at any time the server sends a message to the browser, the onmessage callback is fired. The event handler gets an event object, with the data
property of the object containing the received message. The connection.send() method can be used to send binary data as well. To do so you can use either a Blob or an ArrayBuffer. The following code demonstrates using an ArrayBuffer to send an image drawn on canvas to server.
var image = canvas2DContext.getImageData(0, 0, 440, 300);
var binary_data = new Uint8Array(image.data.length);
for (var i = 0; i < image.data.length; i++) {
  binary_data[i] = image.data[i];
}
connection.send(binary_data.buffer);
Similarly, the received message can be a string or binary data. The binary data can be received as a blob or an arraybuffer.

Simple WebSocket Application

In order to a create a working application, you also need a server side implementation. It’s possible to use technologies like node.js, Java, .NET, Ruby, or C++ to create server side implementation. This section will show you how to create a simple application using WebSockets. The sample application will allow the user to ask specific questions to server. The server side implementation is done using the Java jWebSocket framework on Windows 7. So, to get the environment set up follow these simple steps. I assume you have already installed the latest JDK (JDK 7)on your Windows 7 PC.

Step 1

Head over to jWebSocket Downloads
and download the first zip which is marked as server.

Step 2

Unzip the archive, and place it somewhere in your C:. Then, create a new environment variable named JWEBSOCKET_HOME, which references the root of your jWebSocket installation. This is the path to the jWebSocket-1.0 folder. Add the following JARs to your class path:
  • JWEBSOCKET_HOME/libs/jWebSocketServer-1.0.jar
  • JWEBSOCKET_HOME/libs/jWebSocketServerAPI-1.0.jar
  • JWEBSOCKET_HOME/libs/jWebSocketCommon-1.0.jar

Step 3

Create a new Java Source file and name it SocketListener.java
. Add the following code to this file.
import java.util.Date;
import java.text.SimpleDateFormat;
import org.jwebsocket.factory.JWebSocketFactory;
import org.jwebsocket.server.TokenServer;
import org.jwebsocket.kit.WebSocketServerEvent;
import org.jwebsocket.api.WebSocketServerListener;
import org.jwebsocket.api.WebSocketPacket;
import org.jwebsocket.config.JWebSocketConfig;
import org.jwebsocket.instance.JWebSocketInstance;
class JWebSocketListener implements WebSocketServerListener {
  public void processOpened(WebSocketServerEvent event) {
    System.out.println("Connection Opened");
  }
  public void processPacket(WebSocketServerEvent event, WebSocketPacket packet) {
    switch(packet.getString()){
      case "1":
        packet.setString("My Name is jWebSocketServer");
        break;
      case "2":
        packet.setString("Windows 7 64 Bit");
        break;
      case "3":
        SimpleDateFormat sdf=new SimpleDateFormat("hh:mm:ss");
        packet.setString(sdf.format(new Date()));
        break;
    }
    event.sendPacket(packet);
  }
  public void processClosed(WebSocketServerEvent event) {
  }
}
public class SocketListener{
  public static void main(String[] args){
    JWebSocketFactory.printCopyrightToConsole();
    JWebSocketConfig.initForConsoleApp(new String[]{});
    JWebSocketFactory.start();
    TokenServer server = (TokenServer)JWebSocketFactory.getServer("ts0");
    if(server!=null) {
      server.addListener(new JWebSocketListener());
    }
    while (JWebSocketInstance.getStatus() != JWebSocketInstance.SHUTTING_DOWN){
      try {
        Thread.sleep(250);
      }
      catch (InterruptedException e) {
      }
    }
  }
}

Explanation

The code implements the WebSocketServerListener interface. The interface declares the following three methods which should be implemented in our class, JWebSocketListener.
  • processOpened()
  • processPacket()
  • processClosed()
processOpened() is called once a connection is opened. An example use of this will be starting a thread that sends updates to client in regular intervals. Similarly, processClosed() is called when the connection closes so that you can perform any clean ups. In our application, the major processing is done in processPacket(). This method is called whenever the browser sends a message to the server. It receives two objects, of types WebSocketServerEvent and WebSocketPacket
. First, we use WebSocketPacket#getString() to read the message (which is a question asked by the client). Depending on the question the server sends an answer. The message to be sent is wrapped inside a WebSocketPacket using WebSocketPacket#setString(). Then, we call WebSocketServerEvent#sendPacket(), passing the packet as an argument. Next, we create a public class called SocketListener
. This class starts a WebSocket implementation server and registers our custom listener to it.

Step 4

Compile SocketListener.java, and start your server using the command java SocketListener.

Step 5

Now that you have done the server side implementation, it’s time to create the client that will interact with the server. The following is our initial HTML markup:
<html>
  <head>
    <title>WebSocket Test</title>
    <style>
      #response{
        width: 200px;
        background: #F2F2F2;
        padding: 120px 0px 120px 0px;
        font-size:18px;
      }
    </style>
  </head>
  <body>
    <div align="center">
      Choose a question to ask:
      <select id="question" name="question" onchange="sendMessage(this.value);">
        <option value="1">What's Your Name</option>
        <option value="2">Which OS You Are Running On?</option>
        <option value="3">What Time Is It?</option>
      </select>
      <br/><br/>
      <div id="response">
        My Name is jWebSocketServer
      </div>
    </div>
  </body>
</html>
Now, add the following JavaScript to the HTML:
<script type="text/javascript">
var connection = new WebSocket('ws://localhost:8787', 'json');
connection.onopen = function () {
  console.log('Connection Opened');
};
connection.onerror = function (error) {
  console.log('WebSocket Error ' + error);
};
connection.onmessage = function (e) {
  if(e.data.indexOf("subProtocol")==-1)
    document.getElementById("response").innerHTML=e.data+"<br/>";
};
function sendMessage(msg){
  connection.send(msg);
}
</script>

Explanation

We created an HTML file that allows users to choose questions from a drop down menu. When an onchange event fires, we take the value of the selected item and send that value to the server. The server then processes the request and sends back an answer to the browser. When the message from the server is received, the onmessage callback is executed, which shows the response in the response
<div>. The line if(e.data.indexOf("subProtocol")==-1) is not mandatory. I have included it because initially when the connection is opened, the server sends a long string containing information to the browser. As we don’t want to show this string, I have included the above condition. Note: Don’t directly open this HTML file. Put it in the localhost server and then access it in the browser.

Conclusion

Using the WebSocket API, you can create very powerful real time applications. But, keep in mind that cross origin communication is allowed by WebSockets. So, you should only communicate with servers and clients that you trust. The following are a few example apps that you can create with this API:
  • Realtime Social Stream Updating
  • HTML5 Multiplayer Games
  • Online Chat Applications
Check out Mozilla Developer Network to learn more about the WebSockets API.

Frequently Asked Questions about HTML5 WebSockets API

What is the main difference between HTTP and WebSockets?

HTTP (Hypertext Transfer Protocol) is a stateless protocol that allows for communication between client and server. It is request-response based, meaning the client sends a request and waits for a response from the server. On the other hand, WebSockets is a protocol that provides full-duplex communication channels over a single TCP connection. This means that data can be sent and received simultaneously without the need for a request-response cycle. This makes WebSockets more efficient for real-time applications where data needs to be updated frequently and instantly.

How do I establish a WebSocket connection?

To establish a WebSocket connection, you need to create a new WebSocket object and provide the URL of the server you want to connect to. The URL should start with ‘ws://’ for unencrypted connections and ‘wss://’ for encrypted connections. Once the connection is established, you can send data to the server using the ‘send’ method and receive data from the server by listening to ‘message’ events.

What are the different ready states of a WebSocket connection?

A WebSocket connection can be in one of four states: CONNECTING (0), OPEN (1), CLOSING (2), and CLOSED (3). The ‘readyState’ property of the WebSocket object can be used to determine the current state of the connection.

How can I handle errors in a WebSocket connection?

You can handle errors in a WebSocket connection by listening to the ‘error’ event. This event is fired when an error occurs on the connection. The event object does not provide specific details about the error, but it can be used to trigger error handling logic.

Can I use WebSockets with PHP?

Yes, you can use WebSockets with PHP. However, PHP is not natively designed for long-lived connections like WebSockets. You would need to use a library or framework that supports WebSockets, such as Ratchet or ReactPHP.

What is the role of the WebSocket API in AWS Serverless applications?

In AWS Serverless applications, the WebSocket API plays a crucial role in enabling real-time, two-way communication between clients and servers. It allows you to build real-time applications without having to manage or provision servers.

How secure are WebSockets?

WebSockets can be as secure as you make them. They support the same origin policy, meaning a WebSocket server can only be connected to from the same origin. Additionally, you can use ‘wss://’ (WebSocket Secure) for encrypted connections, which is the WebSocket equivalent of HTTPS.

Can I use WebSockets in all browsers?

Most modern browsers support WebSockets. However, it’s always a good idea to check the specific browser compatibility if you’re planning to use WebSockets in a web application.

How do I close a WebSocket connection?

You can close a WebSocket connection by calling the ‘close’ method on the WebSocket object. This will trigger the ‘close’ event on the server and any clients listening for it.

Can I send binary data over a WebSocket connection?

Yes, you can send binary data over a WebSocket connection. The WebSocket API supports sending and receiving binary data in the form of Blob and ArrayBuffer objects.