Welcome to impressit

Menu
Tech
/02.02.2023/13 min.

A Simple Guide to WebSockets

Andriy Lekh
Andriy LekhCo-Founder and CTO

With the rising number of users on the web, there is a growing issue of connectivity, seamless communication, and downtime. People who use the Internet expect a response to their input almost immediately, which means in real-time. The Hypertext Transfer Protocol (HTTP) has been on guard of data sharing without delays for many years. Yet, with the rise of the overload, experts started thinking about different protocols that could handle the influx of user requests. It was the moment when WebSocket entered the picture in 2011. 

Since then, WebSockets have proved a crucial tool for building web apps capable of providing instant, real-time updates. Keeping that in mind, to understand how the tool does this, it is vital to explore several key areas — what are WebSockets, how do WebSockets work, why these are useful for building real-time apps, and challenges with WebSockets to consider. Besides, we will go through a step-by-step process of setting up the WebSocket server and client. 

 

What are WebSockets

In technical terms, a WebSocket is a full-duplex bidirectional protocol using client-server communication as its foundation. In payment terms, a WebSocket is a system or rules programmed for exchanging data between a server and a client in both ways. 

Importantly, unlike the WebSocket’s predecessor — HTTP, this protocol starts with we:// or wss// instead of http:// or https://. WebSockets, ensure the server-client connection is ongoing and ceases only when either client or server terminates it. 

What are WebSockets used for? As a communication protocol, WebSockets are used for establishing two-way communication between the parties involved, usually a server and a client. The approach ensures a stable and seamless exchange of messages, which entails sending and receiving inputs on both ends. 
 

How does WebSockets Work? 

When it comes to understanding how WebSocket operates, several vital aspects must be considered. Focus on these elements:

  1. In most cases, before server-client data exchange is possible, one should adopt the Transport Control Protocol (TCP). WebSockets, in turn, have their transport layer to enable data exchange. 
  2. Then, the clients get a connection through HTTP request-response pair, which uses an upgrade header to change the connection from HTTP to a WebSocket. 
  3. This creates the opportunity to use a WebSocket handshake via TCP. 
  4. With the WebSocket handshake up and running, the client communicates with the server through subprotocols, which will stay the same throughout the entire session. 
  5. Finally, one can state that the client-server connection is established through the WebSocket protocol. 

Considering the steps above, here is what the initial request header looks like:

GET ws://WebSocket.example.com/ HTTP/1.1

Origin: http://example.com

Connection: Upgrade

Host: WebSocket.example.com

Upgrade: WebSocket

In turn, if the server accepts the request and “agrees” with the upgrade, it sends the following response:

HTTP/1.1 101 WebSocket Protocol Handshake

Date: Wed, 16 Oct 2013 10:07:34 GMT

Connection: Upgrade

Upgrade: WebSocket

Keep in mind that running the WebSocket protocol layer is based on a Uniform Resource Identifier (URI). These are ws:// and wss://. Without URI, the system won’t run. At this point, knowing when to use WebSockets is crucial to explore its key types. 
 

WebSockets Key Types 

WebSockets Key Types

In a nutshell, WebSockets come in different shapes and sizes. However, when it comes to the well-recognized and widely used ones, you should consider these:

  • WebSockets Nginx. Nginx WebSockets are primarily used for enterprise software development. These utilize the power of multiple WebSocket servers, thus offering high performance and constant availability. 
  • Flask WebSockets. WebSockets Flask is a type of low-latency WebSocket providing access to a range of Python, Java, Swift, and Javascript libraries. These WebSockets are known for their versatility.
  • WebSockets Django. Django WebSockets often come with asynchronous support. It means you get clear guidelines for establishing and maintaining WebSocket connections and requests. The platform uses Django Channels to achieve the above.
  • Laravel WebSockets. This type of WebSockets operates under Pusher API. It comes with a debugging dashboard and real-time statistics. Besides, with Lavarel, you can create various custom WebSocket controllers. 
  • Spring WebSockets. Spring is an excellent solution for creating the subprotocols we mentioned above. Essentially, it is a type of WebSocket’s layer operating above TCP. 
  • C++ WebSockets. WebSockets based on the C++ library provide a portable, lightweight, and flexible solution for establishing server-client communication. 
  • Gorilla WebSockets. This WebSocket type offers a stable API package. 

At this point, choosing among the elements above is essential in finding the WebSocket solution to meet your business needs. In the context of this article, we will focus on WebSockets with an emphasis on real-time applications. 

 

Why WebSockets Help Build Real-time Applications

In most cases, WebSockets are best suited for developing real-time applications. The process requires a constant data display on the client’s end. Essentially, as a part of the app’s backend framework, the server sends data to the client, and WebSocket ensures this data stream is uninterrupted and stable. As a result, a real-time app performs steadily, and a user gets a great experience using the product. 

Moreover, when helping build real-time applications, WebSockets offers the following unique features:

  • Real-time updates with open communication lines.
  • Backward compatibility with HTML documents means Chrome, Firefox, and Safari supports WebSockets.
  • Multiplatform compatibility with WebSockets working on mobile, web, and desktop.
  • A single server can handle multiple WebSocket connections.
  • Streaming via various proxies and firewalls.

With the insights above, sufficient evidence suggests WebSockets are crucial for building real-time applications. With the established context, it is time to proceed to a practical guide for setting up a WebSocket server and a client. 

 

Setting up a WebSocket Server

When setting up a WebSocket server, there are several key steps to follow and various prerequisites to consider. When preparing the server, you must choose which programming language and library to use. 

 

Prerequisites for Setting up a WebSocket Server

Starting with system requirements, the key aspect behind setting up a WebSocket server is to have TPC up and to run and listen to incoming connections. Writing a WebSocket server without any external dependencies is possible in such a case. It means it will run on a TCP library only. 

However, several options exist considering external languages and libraries:

  • Python-based WebSocket server. To tap into this approach, you must create a client.py file and import all the given packages within the server code. Next, one should create a coroutine or a Python asynchronous function — async def test(). 
  • Node.js WebSocket server. To start with the Websocker server based on Node.js, you need to create the following event — const WebSocker = new WebSocket (ws://localhost:443). 
  • WebSocket server Java. When tapping into Java-based libraries, follow these steps:
    1. Run the following command — gradle init --type java-library
    2. Choose Groovy for a scripting language
    3. Choose JUnit Jupiter for a testing framework
    4. Leave Project name — default
    5. Leave Source package — default

These are well-recognized programming languages and libraries used to set up a WebSocket server. Yet, when dealing with this protocol, you will find out that WebSocket libraries are basically located on top of different libraries, for instance .NET. 

In addition, with WebSocket servers, you need to consider creating WebSocket proxies. Any communication within WebSockets can be in place only when forward proxies are in place. Yet, along with setting the server, you also need to configure proxies properly. 

Finally, there is a matter of Server-Sent Events (SEEs) vs. WebSocket. In a nutshell, SSEs are mono-directional, while WebSockets are bidirectional. In such a case, if you need push functionality added to your real-time app, both are options to consider. At this point, the elements above are the ones to look at before starting with the WebSocket server. 
 

Steps for Creating a WebSocket Server

To create the WebSocket server, we have chosen a JavaScript library. Without further ado, let’s proceed to the server setting up process, which entails four steps: 

Creating a WebSocket Server

Setting up a simple HTTP server

As mentioned above, WebSockets need to have HTTP to build upon them. To set up a WebSocket server, you first need to set up a basic HTTP server. This server will be capable of accepting connections and serving messages. So, start by creating server.js file and include the following code:

package main

import (

    "fmt"

    "net/http"

)

func main() {

    http.HandleFunc("/", func (w http.ResponseWriter, r *http.Request) {

        fmt.Fprintf(w, "Setting up the server!")

    })

    http.ListenAndServe(":8080", nil)

}

Then, you should run the server with go run server.js. If you have done everything correctly, when visiting localhost:3000, you will see this — Setting up the server!

 

Handshake initiation

With an HTTP server running, you need to set up a WebSocket connection with a one-time handshake. In short, as we mentioned at the beginning of the article, to get the WebSocket protocol, you need to upgrade the server above. It is done through Upgrade() method. Besides, to close the connection, you need to defer keyword. At this point, modify server.js file by including the following code:

conn, err := upgrader.Upgrade(w, r, nil)

if err != nil {

log.Print("upgrade failed: ", err)

return

}

defer conn.Close()

 

Connections

After having the WebSocket protocol, the next step is to create a new WebSocket connection. To do that, you need to use this function:

// Create a new WebSocket.

var socket = new WebSocket('ws://echo.WebSocket.org');

You can change the

with an event listener to show that a connection was established. This is possible with the following code:

// Show a connected message when the WebSocket is opened.

socket.onopen = function(event) {

 socketStatus.innerHTML = 'Connected to: ' + event.currentTarget.url;

 socketStatus.className = 'open';

};

 

Sending and receiving messages

To send messages, you need to add sell() method to the WebSocket protocol. To do that, update your server.go with the following code:

// Send a message when the form is submitted.

form.onsubmit = function(e) {

  e.preventDefault();

// Retrieve the message from the textarea.

  var message = messageField.value;

// Send the message through the WebSocket.

  socket.send(message);

// Add the message to the messages list.

  messagesList.innerHTML += '

  • Sent:' + message +
  •                             '';

    // Clear out the message field.

      messageField.value = '';

    return false;

    };

    The code indicates that the message needs to be retrieved and sent through the Webscoket protocol. When receiving the message, the particular event must be fired. Besides, the event must include a property to access the message itself. Let’s name these as message event and data property. Receiving messages comes with this code:

    // Handle messages sent by the server.

    socket.onmessage = function(event) {

      var message = event.data;

      messagesList.innerHTML += '

  • Received:' +
  •                              message + '';

    };

    As a result, with the server above, you can initiate the handshake and have features for sending and receiving messages. It is time to set up a client as a second part of the equation.

     

    Creating a WebSocket Client

    Setting up a WebSocket client includes some elements comparable to setting up a WebSocket server. Yet, there are particular differences involved as well. Let’s take a look at both of them more closely.

     

    Prerequisites for Creating a WebSocket Client

    First and foremost, you must choose programming languages and libraries to use as the foundation. You can select these well-recognized options from: 

    • Python WebSocket client. With client uses a Python library that focuses on simplicity and performance.
    • WebSocket client Java. With Java-based libraries, you get stability.
    • Node.js WebSocket client. Node.js libraries are multifunctional and can help manage multiple WebSockets in real-time. 

    Moreover, if nothing from above suits your purposes, you can always choose from WebSocket’s internal libraries. These can be SockJSSocket.io, and/or WS

    Next, after choosing the needed programming language and library, it is time to deal with the WebSocket test client. It is a simple yet useful tool to design custom-made WebSocket requests and handle responses. This allows you to test WebSocket services directly. To use the WebSocket test client, follow these steps:

    1. Copy WebSocket server URL.
    2. Paste the URL into the tool.
    3. Click Open.
    4. Click Send after inputting the request text.
    5. As an output, the Log will show response messages.

    At this point, following the aspects above presents the key prerequisites for setting up a WebSocket client. Furthermore, you proceed with creating a WebSocket client itself. 

     

    Steps for Creating a WebSocket Client

    For our Webscoket client, we will use JavaScript Object Notation (JSON) format. The reason for such a choice is that it is lightweight and easy to read and write. So, to set up a WebSocket client with JSON, you need to follow these four steps:

    Steps for Creating a WebSocket Client

    Building a WebSocket object

    First and foremost, to communicate through a WebSocket protocol, you need to open an automatic connection with a WebSocket server by creating a WebSocket object. Consider this parameter:

    WebSocket = new WebSocket(url, protocols);

    In the code, instead of url, type in the URL to which the WebSocket server will respond. It should use the wss:// configuration. In terms of protocols, the software will assume an empty string if there is no specification of which protocol string should be used. Keep in mind if you use an insecure connection, the WebSocket constructor will indicate a SecurityError


    Sending data to the WebSocket server

    If there are no security errors in the previous step, you have your WebSocket object intact. Now, it is time to transmit data to the server. Use send() method for each message you send. It will look like this:

    exampleSocket.send("Lorem Ipsum!");

    Yet, sending a message right after the WebSocket object was created does not mean you will succeed at once. Asynchronous connections are prone to fail. To raise your chances of success, define an onopen event handler. Now, the new code will look like this:

    exampleSocket.onopen = (event) => {

      exampleSocket.send("Lorem Ipsum!");

    };

    The method above is good for sending simple messages. However, if you need to transmit complex data to the WebSocket server, it is better to use frameworks like JSON. In such a case, the code will be the following:

    // Send text to all users through the server

    function sendText() {

      // Construct a msg object containing the data the server needs to process the message from the chat client.

      const msg = {

        type: "message",

        text: document.getElementById("text").value,

        id:   clientID,

        date: Date.now()

      };


     

      // Send the msg object as a JSON-formatted string.

      exampleSocket.send(JSON.stringify(msg));


     

      // Blank the text input element, ready to receive the next line of text from the user.

      document.getElementById("text").value = "";

    }

    Now, when you have written the code for a WebSocket object and sent messages to the server, it is important to take the next step — write code for receiving data from the server to the client. 

    Receiving data from the WebSocket server

    As an event-driven API, WebSockets works so that when data is received, a message event is directed to the WebSocket object. In such a case, to deal with it, you need to use onmessage handler. As a result, you should get something like this:

    exampleSocket.onmessage = (event) => {

      console.log(event.data);

    }

    The further substep is all about getting and interpreting JSON objects. The code interpreting the messages coming to the client should include the elements like login handshake, the text of the message, and user list updates. These are the code:

    exampleSocket.onmessage = (event) => {

      const f = document.getElementById("chatbox").contentDocument;

      let text = "";

      const msg = JSON.parse(event.data);

      const time = new Date(msg.date);

      const timeStr = time.toLocaleTimeString();

      switch (msg.type) {

        case "id":

          clientID = msg.id;

          setUsername();

          break;

        case "username":

          text = `User ${msg.name} signed in at ${timeStr}
    `;

          break;

        case "message":

          text = `(${timeStr}) ${msg.name} : ${msg.text}
    `;

          break;

        case "rejectusername":

          text = `Your username has been set to ${msg.name} because the name you chose is in use.
    `;

          break;

        case "userlist":

          document.getElementById("userlistbox").innerHTML = msg.users.join("
    ");

          break;

      }


     

      if (text.length) {

        f.write(text);

        document.getElementById("chatbox").contentWindow.scrollByPages(1);

      }

    };

    Keep in mind that messages received from the WebSocket forms are in UTF-8 format. 


    Ceasing the client-server connection

    Finally, when the client-server connection is complete, and you are finished with sending and receive messages, you need to close the connection with close() WebSocket method. Ceasing the connection looks like this:

    exampleSocket.close();

    At this point, you know how to initialize both ends of the WebSocket protocol and exchange data. Yet, keep in mind that WebSocket should not be utilized when mixed content is involved, namely because there are security considerations involved. 

     

    Building a Real-time Application with WebSockets

    What are WebSockets used for? We presented the general answer to this question above. While Websockers are great for real-time apps, the protocols can also be used for the following purposes:

    • Chat apps. These represent a simple use of a WebSocket protocol. A user sends a direct message to the server. A server pushes messages to the recipient without any delay. 
    • Gaming apps. The WebSocket protocol is great for multiplayer games. These games need to have a server storing key data — game states. Every move a user makes eventually updates the game state within a server. With WebSockets, it happens much faster than with HTTP.
    • Collaboration apps. In this case, WebSockets are great when you need to work in a collaborative environment, for instance, to edit a shared doc. The approach makes the doc’s state on the server instantly updated and visible to all the users with access to it.  

    As a result, you can see how WebSocket can help build real-time apps with different adoptions. From chatting to data visualization, this protocol offers speed and flexibility. Besides, it can work with multiple clients at the same time. 

     

    Tips for Designing a Real-time App with WebSockets

    If you want your app to use WebSocket protocol properly while also maintaining performance and downtime, here are seven tips to consider.

    1. Keep an eye on latency. Real-time apps should have low latency, which means the Webscokets you use must have a stable connection.
    2. Think of scalability in advance. Be ready for your app and WebSocket to handle an influx of requests and clients.
    3. Security must be a top priority. Implement authentication and encryption. 
    4. Don’t put away error handling. Have error-handling and recovery tools at all times when dealing with real-time apps and WebSockets.
    5. Your apps must deliver high-quality services. In all of the cases above, always remember that your app must, first and foremost, create customer value and deliver a great user experience. 
    6. Focus on data synchronization. Adopt conflict resolution mechanisms across all clients. 
    7. Don’t underestimate bandwidth consumption. Think about optimization and compression instruments to decrease the volume of data transmitted. 

    The tips above are crucial for starting with real-time apps and WebSockets. The more such apps you build, the more you understand the value of concepts like latency, security, and bandwidth. 

     

    Common Challenges with WebSockets

    When it comes to WebSockets security, you cannot go light. To do your best with WebSockets, you must know what typical challenges may arise. So, be prepared to deal with these issues:

    • The connection within WebSocket can be lost, which leads to connection errors. It means you need to double-check the load balancing and reconnecting mechanisms. 
    • WebSockets still does not have support within many proxy servers.
    • Unlike HTTP, WebSockets does not support caching. 
    • There can be a challenge with scaling. For instance, one of the key open-source resources Socket.io,  does not support quick growth.
    • Moving WebSocket server capacity to the cloud can be problematic.
    • The client you use might not be compatible with the WebSocket’s server version.

     

    Conclusion

    So, let’s sum up all of the above. What is a WebSocket? It is a fast and flexible protocol that came out as a substitute for HTTP. When to use WebSockets? When you need to build a real-time app, to have to send and receive data without delays. What is WebSockets used for? They are used for multiple things, from chatting apps to collaborative apps. One can say that shortly, the list will be even longer. Yet, with both WebSockets and HTTP, you need to prioritize security and keep in mind that any app out there should provide high-quality services. 

    Andriy Lekh

    Andriy Lekh

    Co-Founder and CTO
    Seasoned software architect with a decade of experience leads technical teams through projects delivery process.

    Other articles