Create a WebSocket Client in JavaScript

This post shows how to implement a WebSocket client in Java Script and HTML 5 using the WebSocket interface provided by most modern browsers (IE10+, Chrome 16+, Firefox 11+, Safari 6+). A web page that maintains a WebSocket client connection to a WebSocket server endpoint can exchange data with the server in real-time and with low latency over a persistent, full-duplex connection. The client can receive data via a server push and therefore the need for implementing polling is removed. See the below post on how to implement a WebSocket server in Java:

Summary

  1. Implementation of WebSocket Client in Java Script
  2. Simple HTML Page for Testing the WebSocket Client Code
  3. WebSocket Server Code used in this Example
  4. Running the WebSocket Client Example
  5. Debugging WebSocket Connections with Google Chrome Developer Tools
  6. Monitoring WebSocket Traffic with Wireshark

Related Posts

1  Implementation of WebSocket Client in Java Script

Below is the JavaScript source code of a file named wsclient.js which will be included in an HTML 5 page to enable it to open a WebSocket connection. The script contains the code to create a WebSocket client using the WebSocket interface See line 37 for how this class is used:

new WebSocket(webSocketURL)
var webSocket   = null;
var ws_protocol = null;
var ws_hostname = null;
var ws_port     = null;
var ws_endpoint = null;

/**
 * Event handler for clicking on button "Connect"
 */
function onConnectClick() {
    var ws_protocol = document.getElementById("protocol").value;
    var ws_hostname = document.getElementById("hostname").value;
    var ws_port     = document.getElementById("port").value;
    var ws_endpoint = document.getElementById("endpoint").value;

    openWSConnection(ws_protocol, ws_hostname, ws_port, ws_endpoint);
}

/**
 * Event handler for clicking on button "Disconnect"
 */
function onDisconnectClick() {
    webSocket.close();
}

/**
 * Open a new WebSocket connection using the given parameters
 */
function openWSConnection(protocol, hostname, port, endpoint) {
    var webSocketURL = null;

    webSocketURL = protocol + "://" + hostname + ":" + port + endpoint;

    console.log("openWSConnection::Connecting to: " + webSocketURL);

    try {
        webSocket = new WebSocket(webSocketURL);

        webSocket.onopen = function(openEvent) {
            console.log("WebSocket OPEN: " + JSON.stringify(openEvent, null, 4));

            document.getElementById("btnSend").disabled       = false;
            document.getElementById("btnConnect").disabled    = true;
            document.getElementById("btnDisconnect").disabled = false;
        };

        webSocket.onclose = function (closeEvent) {
            console.log("WebSocket CLOSE: " + JSON.stringify(closeEvent, null, 4));

            document.getElementById("btnSend").disabled       = true;
            document.getElementById("btnConnect").disabled    = false;
            document.getElementById("btnDisconnect").disabled = true;
        };

        webSocket.onerror = function (errorEvent) {
            console.log("WebSocket ERROR: " + JSON.stringify(errorEvent, null, 4));
        };

        webSocket.onmessage = function (messageEvent) {
            var wsMsg = messageEvent.data;
            console.log("WebSocket MESSAGE: " + wsMsg);

            if (wsMsg.indexOf("error") > 0) {
                document.getElementById("incomingMsgOutput").value += "error: " + wsMsg.error + "\r\n";

            } else {
                document.getElementById("incomingMsgOutput").value += "message: " + wsMsg + "\r\n";
            }
        };

    } catch (exception) {
        console.error(exception);
    }
}

/**
 * Send a message to the WebSocket server
 */
function onSendClick() {

    if (webSocket.readyState != WebSocket.OPEN) {
        console.error("webSocket is not open: " + webSocket.readyState);
        return;
    }

    var msg = document.getElementById("message").value;
    webSocket.send(msg);
}

2  Simple HTML Page for Testing the WebSocket Client Code

A simple HTML 5 page is used here to create a form for connecting to a WebSocket server endpoint and for exchanging messages. The HTML page uses the wsclient.js script shown earlier and is shown in the screenshot below.

WebSocket Client - HTML 5 Page with WebSocket Connection Form

The source code of the page is shown below. Note line 6, where the JavaScript file is included. This file contains the JavaScript logic to implement a WebSocket client.

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
      <meta http-equiv="Content-Security-Policy"  content="connect-src * 'unsafe-inline';">
        <script src="wsclient.js"></script>
        <style>
            table    { border: 2px solid black; }
            input    { width: 300px; }
            select   { width: 300px; }
            textarea { width: 513px; border: 2px solid black; }

            #btnConnect    { width: 100px; }
            #btnDisconnect { width: 100px; }
            #btnSend       { width: 100px; }
        </style>
    </head>
    <body>
        <h1>WebSocket Client</h1>
        <!-- WebSocket Connection Parameters Table -->
        <table>
            <tr>
                <td width="200px">WS Protocol</td>
                <td>
                    <select id="protocol">
                        <option value="ws" selected="selected">ws</option>
                        <option value="wss">wss</option>
                    </select>
                </td>
            </tr>
            <tr>
                <td>WS Hostname</td>
                <td><input type="text" id="hostname"/></td>
            </tr>
            <tr>
                <td>WS Port</td>
                <td><input type="text" id="port"/></td>
            </tr>
            <tr>
                <td>WS Endpoint</td>
                <td><input type="text" id="endpoint"/></td>
            </tr>
            <tr>
                <td></td>
                <td>
                    <input id="btnConnect"    type="button" value="Connect"    onclick="onConnectClick()">&nbsp;&nbsp;
                    <input id="btnDisconnect" type="button" value="Disconnect" onclick="onDisconnectClick()" disabled="disabled">
                </td>
            </tr>
        </table><br/>
        <!-- Send Message Table -->
        <table>
            <tr>
                <td width="200px">Message</td>
                <td><input type="text" id="message"/></td>
            </tr>
            <tr>
                <td></td>
                <td>
                    <input id="btnSend" type="button" value="Send Message" disabled="disabled" onclick="onSendClick()">
                </td>
            </tr>
        </table><br/>
        <textarea id="incomingMsgOutput" rows="10" cols="20" disabled="disabled"></textarea>
    </body>
</html>

To run this HTML file, open it in a browser, such as Google Chrome by selecting File > Open.

3  WebSocket Server Code used in this Example

A simple WebSocket server can be implemented easily in Java. The code used in this example is shown below. This server simply returns a message, which it received from a client, in uppercase. This WebSocket server is deployed on Tomcat 9 with a context root of /WebSocketServer. For a step-by-step guide on how to run a WebSocket server with Java and Tomcat, see the post:

package com.pgx.java.web;

import java.io.IOException;
import javax.websocket.OnClose;
import javax.websocket.OnError;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;

@ServerEndpoint("/echo")
public class EchoWebSocket {

    @OnOpen
    public void onOpen(Session session) {
        System.out.println("onOpen::" + session.getId());        
    }

    @OnClose
    public void onClose(Session session) {
        System.out.println("onClose::" +  session.getId());
    }
    
    @OnMessage
    public void onMessage(String message, Session session) {
        System.out.println("onMessage::From=" + session.getId());
        
        try {
            session.getBasicRemote().sendText(message.toUpperCase());

        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    
    @OnError
    public void onError(Throwable t) {
        System.out.println("onError::" + t.getMessage());
    }
}

To connect to this WebSocket server endpoint, a URL like the one below is used.

ws://127.0.0.1:8080/WebSocketServer/echo

4  Running the WebSocket Client Example

Open the wsclientform.html shown earlier in a web browser and enter the required WebSocket connection parameters as shown below and then click on the Connect button. If the connection was established successfully, the button will be disabled and the Disconnect button will be enabled.

WebSocket Client - Use HTML 5 Page to Open WebSocket Connection

Enter a message in the Message text field and click on the send button. The WebSocket server will echo the given message in uppercase characters and the JavaScript client will show the message in the textarea.

5  Debugging WebSocket Connections with Google Chrome Developer Tools

The Google Chrome Developer Tools is a good tool for examining WebSocket connections.

WebSocket Client - Open Google Chrome Developer Tools on HTML 5 Page

In the Developer Tools window, switch to the Network tab and select WS to view a list of all WebSocket connections for the current page. Click on the Header tab to view the WebSocket connection request- and response headers.

WebSocket Client - View WebSocket Headers with Google Chrome Developer Tools

The Frames tab lists all outgoing and incoming messages. In the below screenshot, the first message is the one that was sent from the client to the server and the second message is the server echo in uppercase characters.

WebSocket Client - View WebSocket Frames with Google Chrome Developer Tools

The Timing tab shows for how long the connection has been open. Since a WebSocket is a persistent connection, there is a message saying: CAUTION: Request is not yet finished.

WebSocket Client - View WebSocket Timing with Google Chrome Developer Tools

The Console can be used to look at the actual WebSocket instance that is within the HTML page’s scope. Simply enter the name of the WebSocket JavaScript variable, here it is webSocket and the console will print a JSON representation of the object.

WebSocket Client - View WebSocket Object with Google Chrome Developer Tools

The readyState property of the WebSocket object stores the status of the connection. A value of 1 means that the connection is open and ready to receive and send messages. It can be used to check the WebSocket connection before attempting to send a message. If the connection is closed, automatic connection opening retry logic could be implemented.

6  Monitoring WebSocket Traffic with Wireshark

Wireshark is a very comprehensive and useful tool to monitor traffic on a network. It can be downloaded for free from www.wireshark.org/download.html. After the installation, run it and select a network interface on which to capture traffic.

WebSocket Client - Select Network Interface in Wireshark to Monitor WebSocket Traffic

To only view WebSocket traffic, enter websocket in the filter field. Click on a frame to examine its contents, including the actual payload of the WebSocket message. Scroll down to the Line-based text data node and expand it.

WebSocket Client - Use Wireshark to View WebSocket Traffic

Right-click on the compressed payload and then select Show Packet Bytes. In the dialog window, select Compressed from the Decode as dropdown control to view the payload in plain text. For additional information on using WireShark to monitor WebSocket traffic, see https://wiki.wireshark.org/WebSocket.

WebSocket Client - Use Wireshark to View WebSocket Messages

Leave a Reply