WebSockets Explained
Learn what a WebSocket is including the WebSocket protocol, WebSocket handshake, WebSocket closing handshake, WebSocket HTTP headers, and how to make a WebSocket application with JavaScript.
Table of Contents 📖
- What is a WebSocket?
- JavaScript WebSocket Example
- WebSocket Handshake
- WebSocket Close Handshake
- When to use WebSocket
What is a WebSocket?
Similar to HTTP, WebSocket is a protocol used in client/server communication. However, HTTP is unidirectional while WebSocket is bidirectional. This means that unlike HTTP where the client sends a request and then the server replies with a response, with WebSocket, messages can be sent from either end of the connection at any time. The WebSocket protocol is specified in a url with ws for unsecure WebSocket and wss for secure WebSocket. For example, we can establish a WebSocket connection on localhost port 1234 with the url ws://localhost:1234.
const clientSocket = new WebSocket('ws://localhost:1234');
Here we use the JavaScript WebSocket API, which is an API for working with WebSocket. This code will look for a WebSocket server on localhost port 1234.
JavaScript WebSocket Example
The WebSocket protocol is built on top of HTTP. Meaning that WebSocket uses the TCP connection formed with HTTP but keeps the connection alive after the HTTP response is received. Specifically, a WebSocket connection is an upgraded HTTP request and response. This upgrade is handled by HTTP headers. To demonstrate, lets form a WebSocket connection between a client and a server using JavaScript. First, lets create the WebSocket client.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script>
const clientSocket = new WebSocket('ws://localhost:1234');
// Fired when a connection with a WebSocket is opened
clientSocket.onopen = event => {
clientSocket.send('Hello server!')
};
// Fired when data is received through a WebSocket
clientSocket.onmessage = event => {
console.log(`Server: ${event.data}`);
};
</ script>
</body>
</html>
Here, the WebSocket client is looking for a connection to ws://localhost:1234. When the connection is opened, it sends Hello server! to the server. When the client receives a message it logs it to the console. Now lets create the WebSocket server.
const http = require('http');
const ws = require('ws');
// Creates an HTTP server
const server = http.createServer();
// Create a websocket server using the provided HTTP server
const webSocketServer = new ws.Server({ server });
/*
* 'connection' event is emitted when the handshake is complete.
* The serverSocket is the socket connection that can be
* used to communicate with the connected entity.
*/
webSocketServer.on('connection', serverSocket => {
// Send data to the connected client
serverSocket.send('Hello client!');
// Fired when a message is received.
serverSocket.on('message', function message(data) {
console.log(`Client: ${data}`);
});
});
server.listen(1234);
Here, an HTTP server is created using the core Node http module createServer function. This server is listening for HTTP connections on localhost:1234. When it receives one, the connection is upgraded to a WebSocket connection. The WebSocket server sends the message Hello client! when it receives a new connection and when it receives a message it prints it to the console. Now, if we open the chrome network tab we can see the headers involved in upgrading from HTTP to WebSocket.
WebSocket Handshake
A WebSocket connection is formed with a WebSocket handshake. The WebSocket handshake consists of HTTP request and HTTP response headers. These are the HTTP request headers involved.
- Connection: Upgrade - Tells the server that the client wants to change the protocol
- Sec-WebSocket-Key:
- A randomly generated base64 encoded value - Sec-WebSocket-Version: 13 - WebSocket protocol version
- Upgrade: websocket - Tells the server to switch to the WebSocket protocol
The server then responds with some HTTP response headers for the WebSocket connection.
- Connection: Upgrade - Tells the client that the server changed the protocol
- Sec-WebSocket-Accept:
- Concatenated Sec-WebSocket-Key value and a static value defined by RFC hashed and encoded - Upgrade: websocket - Tells the client that the server switched to the WebSocket protocol
The response from the server will be a 101 status code which means Switching Protocols. This response code indicates that the server has switched protocols to the one that the client has requested in the HTTP Upgrade header.
WebSocket Close Handshake
When a WebSocket connection closes, a closing frame is sent. A frame is essentially just data. Either the client or server can close the connection and can optionally send the reason for closing the connection. Once the close frame is received by either the server or client, they respond with their own close frame. Finally, the TCP connection is ended.
When to use WebSocket
The use case for the WebSocket protocol is any situation that benefits from bidirectional communication and real time data. In other words, the WebSocket protocol is great for situations where the client/server want continuous updates. This is because the WebSocket protocol offers low latency as the TCP connection has already been established so there is no extra overhead in re-establishing the TCP connection. Furthermore, as the connection is bidirectional the server can send data without receiving a request from the client. A chat application is a classic example of an application that benefits from the WebSocket protocol.