This manual is also available in HTML5.
The WebSocket API is an advanced technology that makes it possible to open a two-way interactive communication session between the user's browser and a server. With this API, you can send messages to a server and receive event-driven responses without having to poll the server for a reply.
Common use cases for the WebSocket API include:
-
Real-time updates: Applications that require real-time data updates, such as live sports scores, stock market updates, or live news feeds.
-
Chat applications: Instant messaging and chat applications where low latency and real-time communication are crucial.
-
Online gaming: Multiplayer online games that need real-time interaction between players.
-
Collaborative tools: Applications like collaborative document editing, where multiple users need to see changes in real-time.
-
IoT (Internet of Things): Communication between IoT devices and servers for real-time data exchange and control.
-
Live streaming: Streaming live audio, video, or other media content to clients.
-
Notifications: Sending real-time notifications to users, such as alerts or updates in web applications. These use cases benefit from WebSocket's ability to maintain a persistent connection, allowing for efficient and low-latency communication between the client and server.
The WebSocket API is defined by the WebSocket interface, which is part of the HTML Living Standard. The API provides a set of methods, properties, and events that enable developers to create WebSocket connections and interact with them in a web application.
The WebSocket API offers several key features that make it a powerful tool for building real-time web applications:
-
Full-duplex communication: WebSockets enable full-duplex communication between the client and server, allowing both parties to send and receive messages simultaneously. This bidirectional communication is essential for real-time applications that require low latency and high interactivity.
-
Persistent connection: Unlike traditional HTTP connections, which are stateless and short-lived, WebSocket connections are persistent and long-lived. Once established, a WebSocket connection remains open until either the client or server decides to close it. This persistent connection eliminates the need to establish a new connection for each message, reducing latency and overhead.
-
Low latency: WebSockets provide low-latency communication by eliminating the need for repeated handshakes and headers in each message exchange. This efficiency allows real-time data to be transmitted quickly and responsively, making WebSockets ideal for applications that require instant updates and notifications.
-
Efficient data transfer: WebSockets use a binary messaging format that is more compact and efficient than text-based formats like JSON or XML. This binary format reduces the size of messages sent over the network, improving performance and reducing bandwidth consumption.
-
Cross-origin communication: WebSockets support cross-origin communication, allowing clients to establish connections with servers hosted on different domains. This feature enables developers to build distributed systems and integrate services from multiple sources in a secure and controlled manner.
-
Secure communication: WebSockets can be used over secure connections (wss://) to encrypt data transmitted between the client and server. This encryption ensures that sensitive information is protected from eavesdropping and tampering, making WebSockets a secure choice for transmitting confidential data.
-
Event-driven architecture: The WebSocket API is event-driven, meaning that clients and servers can respond to specific events, such as message reception, connection establishment, or connection closure. This event-driven architecture simplifies the development of real-time applications by providing a clear and structured way to handle asynchronous communication.
You can install ws13
using this command:
npm install ws13
You can test ws13
on your system using this command:
node ./node_modules/ws13/index.test
or in the ws13
project directory:
npm test
ws13
support ESM and CJS module format in Node.js
import createWebSocket from 'ws13';
// or
const createWebSocket = require('ws13');
Example of use on a server
const { createServer } = require('node:http');
const createWebSocket = require('ws13');
const server = createServer();
let wsList = [];
server.on('upgrade', function (request) {
// upgrade WebSocket
const websocket = createWebSocket({ request });
// has WebSocket, the handshake is done
if (websocket) {
// inserts a WebSocket from the list
wsList.push(websocket);
// add listeners
websocket
.on('error', console.error)
.on('open', function () {
/* now you can send and receive messages */
})
.on('message', function (event) {
// send to everyone
wsList.forEach((ws) => { ws.send(event.data); });
})
.on('close', function () {
// removing a WebSocket from the list
wsList = wsList.filter(ws => ws !== websocket);
});
} else {
// handshake not accepted
request.destroy();
}
});
Example of use as a client
In the client role, a browser-compatible implementation of WebSocket should be preferred, which should provide better results.
If it is important that the same code runs on the client and server side, then do the following.
const http = require('node:http');
const createWebSocket = require('ws13');
const ws = createWebSocket({
request: http.request({
hostname: '127.0.0.1',
port: 80,
path: '/test'
})
})
.on('error', console.error)
.on('open', function () {
/* now you can send and receive messages */
ws.heartbeat(function (latency_ms) { console.log('client latency_ms', latency_ms); });
ws.send('Hello, World!');
})
.on('message', function (event) { console.log('client data', event.data); })
.on('ping', function (event) { console.log('client ping', event); })
.on('pong', function (event) { console.log('client pong', event); })
.on('close', function () { console.log('client websocket is closed'); });
Example of use as a client in the browser
<!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>WebSocket</title>
</head>
<body>
<script>
const ws = new WebSocket('ws://localhost:3000/test');
ws.onopen = function () {
ws.send('Hello, World!');
};
ws.onmessage = function (event) {
console.log('server data', event.data);
};
ws.onclose = function () {
console.log('client websocket is closed');
};
</script>
</body>
</html>
Complete example of use on the server and client side can be found in the examples/chat directory.
Secure communication
To use secure communication, you need to use the https
module and the wss
protocol.
Example of use on a https
server
const { createServer } = require('node:https');
const createWebSocket = require('ws13');
const server = createServer({
// path to the key and certificate
key: fs.readFileSync('server-key.pem'),
cert: fs.readFileSync('server-cert.pem')
});
let wsList = [];
server.on('upgrade', function (request) {
// upgrade WebSocket
const websocket = createWebSocket({ request });
// has WebSocket, the handshake is done
if (websocket) {
// inserts a WebSocket from the list
wsList.push(websocket);
// add listeners
websocket
.on('error', console.error)
.on('open', function () {
/* now you can send and receive messages */
})
.on('message', function (event) {
// send to everyone
wsList.forEach((ws) => { ws.send(event.data); });
})
.on('close', function () {
// removing a WebSocket from the list
wsList = wsList.filter(ws => ws !== websocket);
});
} else {
// handshake not accepted
request.destroy();
}
});
The WebSocket
interface is the main interface for the WebSocket API.
It base the EventEmitter
.
create new instance: createWebSocket(options)
Returns a newly created WebSocket object.
method parameters:
- parameter:
options
Typeobject
.isDebug
Value typeboolean
. If set totrue
, more info in console. Defaultfalse
.request
Value typehttp.IncomingMessage
orhttp.ClientRequest
. Reference (role of server http.IncomingMessage) or (role of client http.ClientRequest)headers
Value typeobject
. Key-value pairs of header names and values. Header names are lower-cased. Defaultrequest.headers
.socket
Value typenet.Socket
. This class is an abstraction of a TCP socket or a streaming IPC endpoint. Defaultrequest.socket
.protocol
Value typestring
. The sub-protocol selected by the server. Default empty string.origin
Value typestring
. String or validation function(origin:string)=>boolean
. Default empty string.heartbeatInterval_ms
Value typenumber
. The interval after which ping pong takes place. Default30000
.extension
Value typeExtension | null
. WebSocket selected extensions ornull
. Defaultpermessage-deflate
.
permessage-deflate is a WebSocket extension that allows messages to be compressed before being sent over the network. This can significantly reduce the amount of data transmitted, especially for large messages or messages with repetitive content, improving performance and reducing bandwidth usage.
Benefits of permessage-deflate:
- Reduced Bandwidth Usage: Compressing messages can lower the amount of data sent over the network, which is particularly beneficial for applications with limited bandwidth.
- Improved Performance: Smaller message sizes can lead to faster transmission times, enhancing the overall performance of real-time applications.
- Cost Savings: Lower bandwidth usage can result in cost savings, especially for applications that handle a large volume of data.
- property:
WebSocket.CONNECTING
Value0
. The connection is not yet open. - property:
WebSocket.OPEN
Value1
. The connection is open and ready to communicate. - property:
WebSocket.CLOSING
Value2
. The connection is in the process of closing. - property:
WebSocket.CLOSED
Value3
. The connection is closed.
- property:
ws.readyState
Value0 | 1 | 2 | 3
. The connection state. - property:
ws.protocol
Value typestring
. Returns the name of the sub-protocol the server selected; this will be one of the strings specified in the protocols parameter when creating the WebSocket object, or the empty string if no connection is established. - property:
ws.path
Value typestring
. - property:
ws.url
Value typestring
. - property:
ws.origin
Value typestring
. - property:
ws.heartbeatInterval_ms
Value typenumber
. - property:
ws.ip
Value typestring
. IP address - property:
ws.port
Value typenumber
. Port number - property:
ws.latency_ms
Value typenumber
. Latency describes the amount of delay on a network or Internet connection. Low latency implies that there are no or almost no delays. High latency implies that there are many delays. One of the main aims of improving performance is to reduce latency.
- method:
ws.close()
Returnsundefined
. Closes the connection. - method:
ws.heartbeat(callback:(latency_ms:number)=>void)
Returnsundefined
. Initiates a ping-pong procedure by measuring its time. - method:
ws.send(data)
Returnsundefined
. Senddata
through the connection. This method throws an error if the ready state isCONNECTING
. - method:
ws.sendPing(data)
Returnsundefined
. Sendping
through the connection. This method throws an error if the ready state isCONNECTING
. - method:
ws.sendPong(data)
Returnsundefined
. Sendpong
through the connection. This method throws an error if the ready state isCONNECTING
.
-
event:
'close'
Fired when a connection with aWebSocket
is closed. Also available via theonclose
propertyEvent type
object
.Event properties:
code
Returns an unsigned short containing the close code sent by the server.reason
Returns a string indicating the reason the server closed the connection. This is specific to the particular server and sub-protocol.wasClean
Returns a boolean value that Indicates whether or not the connection was cleanly closed.
-
event:
'error'
Fired when a connection with aWebSocket
has been closed because of an error, such as when some data couldn't be sent. Also available via thews.onerror
property.Event type
Error
. -
event:
'message'
Fired when data is received through aWebSocket
. Also available via theonmessage
property.Event type
object
.Event properties:
data
The data sent by the message emitter.isBinary
Specifies whether the message is binary or not.
-
event:
'open'
Fired when a connection with aWebSocket
is opened. Also available via theonopen
property.Event type
undefined
. -
event:
'ping'
Fired when ping is received through aWebSocket
. Also available via theonping
property.Event type
object
.Event properties:
data
The data sent by the message emitter.
-
event:
'pong'
Fired when pong is received through aWebSocket
. Also available via theonpong
property.Event type
object
.Event properties:
data
The data sent by the message emitter.latency_ms
Latency describes the amount of delay on a network or Internet connection.
Constant | Value | Description |
---|---|---|
CONNECTING | 0 | The connection is not yet open. |
OPEN | 1 | The connection is open and ready to communicate. |
CLOSING | 2 | The connection is in the process of closing. |
CLOSED | 3 | The connection is closed. |
Extending the interface for permessage-deflate
and permessage-masking
create new Extension: createExtension([options])
Returns a newly created Extension object.
-
method:
ext.init(ws)
Returnsundefined
. Initialisation.method parameters:
- parameter:
ws
TypeWebSocket
.
- parameter:
-
method:
ext.close(callback)
Returnsundefined
. Close extension.method parameters:
- parameter:
callback
Type(error)=>void
.
- parameter:
-
method:
ext.mask(frame, callback)
Returnsundefined
. Mask frame.method parameters:
-
method:
ext.unmask(frame, callback)
Returnsundefined
. Unmask frame.method parameters:
-
method:
ext.generateOffer(callback)
Returnsundefined
. Client generate offer.method parameters:
- parameter:
callback
Type(error, extHeaderValue:string)=>void
. Returnsundefined
.
- parameter:
-
method:
ext.activate(headers, callback)
Returnsundefined
. Client activate.method parameters:
- parameter:
headers
Type[string]
. - parameter:
callback
Type(error, isActivate:boolean)=>void
. Returnsundefined
.
- parameter:
-
method:
ext.generateResponse(headers, callback)
Returnsundefined
. Server generate response.method parameters:
- parameter:
headers
Type[string]
. - parameter:
callback
Type(error, extHeaderValue:string)=>void
. Returnsundefined
.
- parameter:
-
method:
ext.processIncomingMessage(frame, callback)
Returnsundefined
.method parameters:
-
method:
ext.processOutgoingMessage(frame, callback)
Returnsundefined
.method parameters:
-
method:
ext.processIncomingFrame(frame, callback)
Returnsundefined
.method parameters:
-
method:
ext.processOutgoingFrame(frame, callback)
Returnsundefined
.method parameters:
The Frame
interface represents a WebSocket frame.
Frame type object
.
- property:
frame.isFin
Value typeboolean
. - property:
frame.isRsv1
Value typeboolean
. - property:
frame.isRsv2
Value typeboolean
. - property:
frame.isRsv3
Value typeboolean
. - property:
frame.opcode
Value typeboolean
. - property:
frame.isMasked
Value typeboolean
. - property:
frame.payloadLength
Value typenumber
. - property:
frame.maskingKey
Value type[]
. - property:
frame.payload
Value typeBuffer
.
This project is licensed under the MIT License.
Copyright © 2024 Manuel Lõhmus
Donations are welcome and will go towards further development of this project.