The WebSocket
protocol, described in the specification RFC 6455 provides a way to exchange data between browser and server via a persistent connection. The data can be passed in both directions as “packets”, without breaking the connection and additional HTTP requests.
WebSocket is especially great for services that require continuous data exchange, e.g. online games, real-time trading systems, chat apps, and so on.
Creating a WebSocket object
In order to communicate using the WebSocket protocol, you need to create a WebSocket
object; this will automatically attempt to open the connection to the server.
The WebSocket constructor accepts one required and one optional parameter:
webSocket = new WebSocket(url, protocols);
url
- The URL to which to connect; should be the URL to which the WebSocket server will respond. This should use the URL scheme
wss://
, although some software may allow you to use the insecurews://
for local connections. protocols
(Optional)- Either a single protocol string or an array of protocol strings. These strings are used to indicate sub-protocols so that a single server can implement multiple WebSocket sub-protocols (for example, you might want one server to be able to handle different types of interactions depending on the specified
protocol
). If you don't specify a protocol string, an empty string is assumed.
NOTE : The constructor will throw a SecurityError
if the destination doesn't allow access. This may happen if you attempt to use an insecure connection (most user agents now require a secure link for all WebSocket connections unless they're on the same device or possibly on the same network).
A simple example
To open a WebSocket connection, we need to create new WebSocket
using the special protocol ws
in the URL:
let socket = new WebSocket("ws://javascript.info");
There’s also encrypted wss://
protocol. It’s like HTTPS for WebSockets.
Another Example with defined Protocols:
This simple example creates a new WebSocket, connecting to the server at wss://www.example.com/socketserver
. A custom protocol of "protocolOne" is named in the request for the socket in this example, though this can be omitted.
var exampleSocket = new WebSocket("wss://www.example.com/socketserver", "protocolOne");
On return, exampleSocket.readyState
is CONNECTING
. The readyState
will become OPEN
once the connection is ready to transfer data.
If you want to open a connection and are flexible about the protocols you support, you can specify an array of protocols:
var exampleSocket = new WebSocket("wss://www.example.com/socketserver", ["protocolOne", "protocolTwo"]);
Once the connection is established (that is, readyState
is OPEN
), exampleSocket.protocol
will tell you which protocol the server selected.
Establishing a WebSocket relies on the HTTP Upgrade mechanism, so the request for the protocol upgrade is implicit when we address the web server as ws://www.example.com
or wss://www.example.com
.
Once the socket is created, we should listen to events on it. There are totally 4 events:
open
– connection established,message
– data received,error
– WebSocket error,close
– connection closed.
Here’s an example:
let socket = new WebSocket("wss://javascript.info/article/websocket/demo/hello");
socket.onopen = function(e) {
alert("[open] Connection established");
alert("Sending to server");
socket.send("My name is John");
};
socket.onmessage = function(event) {
alert(`[message] Data received from server: ${event.data}`);
};
socket.onclose = function(event) {
if (event.wasClean) {
alert(`[close] Connection closed cleanly, code=${event.code} reason=${event.reason}`);
} else {
// e.g. server process killed or network down
// event.code is usually 1006 in this case
alert('[close] Connection died');
}
};
socket.onerror = function(error) {
alert(`[error] ${error.message}`);
};
Using JSON to transmit objects
One handy thing you can do is use JSON to send reasonably complex data to the server. For example, a chat program can interact with a server using a protocol implemented using packets of JSON-encapsulated data:
// 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.
var 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 = "";
}
Receiving messages from the server
WebSockets is an event-driven API; when messages are received, a message
event is sent to the WebSocket
object. To handle it, add an event listener for the message
event, or use the onmessage
event handler. To begin listening for incoming data, you can do something like this:
exampleSocket.onmessage = function (event) {
console.log(event.data);
}
Receiving and interpreting JSON objects
Let's consider the chat client application first alluded to in Using JSON to transmit objects. There are assorted types of data packets the client might receive, such as:
- Login handshake
- Message text
- User list updates
The code that interprets these incoming messages might look like this:
exampleSocket.onmessage = function(event) {
var f = document.getElementById("chatbox").contentDocument;
var text = "";
var msg = JSON.parse(event.data);
var time = new Date(msg.date);
var timeStr = time.toLocaleTimeString();
switch(msg.type) {
case "id":
clientID = msg.id;
setUsername();
break;
case "username":
text = "<b>User <em>" + msg.name + "</em> signed in at " + timeStr + "</b><br>";
break;
case "message":
text = "(" + timeStr + ") <b>" + msg.name + "</b>: " + msg.text + "<br>";
break;
case "rejectusername":
text = "<b>Your username has been set to <em>" + msg.name + "</em> because the name you chose is in use.</b><br>"
break;
case "userlist":
var ul = "";
for (i=0; i < msg.users.length; i++) {
ul += msg.users[i] + "<br>";
}
document.getElementById("userlistbox").innerHTML = ul;
break;
}
if (text.length) {
f.write(text);
document.getElementById("chatbox").contentWindow.scrollByPages(1);
}
};
Here we use JSON.parse()
to convert the JSON object back into the original object, then examine and act upon its contents.
Text data format
Text received over a WebSocket connection is in UTF-8 format.
Closing the connection
When you've finished using the WebSocket connection, call the WebSocket method close()
:
exampleSocket.close();
It may be helpful to examine the socket's bufferedAmount
attribute before attempting to close the connection to determine if any data has yet to be transmitted on the network. If this value isn't 0, there's pending data still, so you may wish to wait before closing the connection.
Security considerations
WebSockets should not be used in a mixed content environment; that is, you shouldn't open a non-secure WebSocket connection from a page loaded using HTTPS or vice-versa. Most browsers now only allow secure WebSocket connections, and no longer support using them in insecure contexts.