WebSocket Tutorial
WebSocket is a network communication protocol that is required for many advanced functions.
This article describes how to use the WebSocket protocol.
1. Why do you need WebSocket?
Anyone who is new to WebSockets asks the same question: we already have the HTTP protocol, why do we need another protocol? What benefits can it bring?
The answer is simple, because the HTTP protocol has a flaw: communication can only be initiated by the client.
For example, if we want to know today's weather, we can only make a request from the client to the server, and the server returns the query result. The HTTP protocol cannot allow the server to actively push information to the client.
The characteristics of this one-way request are destined to be very troublesome for the client to know if the server has continuous state changes. We can only use "polling" : every once in a while, a query is sent to see if the server has new information. The most typical scenario is the chat room.
Polling is inefficient and wastes resources (because you have to keep connecting, or the HTTP connection is always open). Therefore, engineers have been thinking, is there a better way. That's how WebSocket was invented.
2. Introduction
The WebSocket protocol was born in 2008 and became an international standard in 2011. All browsers already support it.
Its biggest feature is that the server can actively push information to the client, and the client can also actively send information to the server. It is a real two-way equal dialogue and belongs to a kind of server push technology .
Other features include:
(1) Based on the TCP protocol, the server-side implementation is relatively easy.
(2) It has good compatibility with the HTTP protocol. The default ports are also 80 and 443, and the HTTP protocol is used in the handshake phase, so it is not easy to shield during the handshake, and can pass through various HTTP proxy servers.
(3) The data format is relatively lightweight, the performance overhead is small, and the communication is efficient.
(4) Text can be sent, and binary data can also be sent.
(5) There is no same-origin restriction, and the client can communicate with any server.
(6) The protocol identifier is ws
(if encrypted, it is wss
) and the server URL is the URL.
ws://example.com:80/some/path
Third, the simple example of the client
The usage of WebSocket is fairly simple.
The following is an example of a web script (click here to see the running result), which can basically be understood at a glance.
var ws = new WebSocket("wss://echo.websocket.org"); ws.onopen = function(evt) { console.log("Connection open ..."); ws.send("Hello WebSockets!"); }; ws.onmessage = function(evt) { console.log( "Received Message: " + evt.data); ws.close(); }; ws.onclose = function(evt) { console.log("Connection closed."); };
Fourth, the client API
The API of the WebSocket client is as follows.
4.1 WebSocket Constructor
The WebSocket object is used as a constructor to create a new WebSocket instance.
var ws = new WebSocket('ws://localhost:8080');
After executing the above statement, the client will connect to the server.
For a list of all properties and methods of the instance object, see here .
4.2 webSocket.readyState
readyState
The property returns the current state of the instance object, there are four kinds.
- CONNECTING: A value of 0 means connecting.
- OPEN: The value is 1, indicating that the connection is successful and communication is possible.
- CLOSING: A value of 2 means the connection is closing.
- CLOSED: The value is 3, indicating that the connection has been closed or failed to open the connection.
Below is an example.
switch (ws.readyState) { case WebSocket.CONNECTING: // do something break; case WebSocket.OPEN: // do something break; case WebSocket.CLOSING: // do something break; case WebSocket.CLOSED: // do something break; default: // this never happens break; }
4.3 webSocket.onopen
Attribute of the instance object onopen
, used to specify the callback function after the connection is successful.
ws.onopen = function () { ws.send('Hello Server!'); }
If you want to specify multiple callback functions, you can use addEventListener
methods.
ws.addEventListener('open', function (event) { ws.send('Hello Server!'); });
4.4 webSocket.onclose
Attribute of the instance object onclose
, used to specify the callback function after the connection is closed.
ws.onclose = function(event) { var code = event.code; var reason = event.reason; var wasClean = event.wasClean; // handle close event }; ws.addEventListener("close", function(event) { var code = event.code; var reason = event.reason; var wasClean = event.wasClean; // handle close event });
4.5 webSocket.onmessage
Attribute of the instance object onmessage
, used to specify the callback function after receiving server data.
ws.onmessage = function(event) { var data = event.data; // 处理数据 }; ws.addEventListener("message", function(event) { var data = event.data; // 处理数据 });
Note that server data may be text or binary data ( blob
object or Arraybuffer
object).
ws.onmessage = function(event){ if(typeof event.data === String) { console.log("Received data string"); } if(event.data instanceof ArrayBuffer){ var buffer = event.data; console.log("Received arraybuffer"); } }
In addition to dynamically judging the received data type, binaryType
attributes can also be used to explicitly specify the received binary data type.
// 收到的是 blob 数据 ws.binaryType = "blob"; ws.onmessage = function(e) { console.log(e.data.size); }; // 收到的是 ArrayBuffer 数据 ws.binaryType = "arraybuffer"; ws.onmessage = function(e) { console.log(e.data.byteLength); };
4.6 webSocket.send()
The methods of the instance object are send()
used to send data to the server.
Example of sending text.
ws.send('your message');
Example of sending a Blob object.
var file = document .querySelector('input[type="file"]') .files[0]; ws.send(file);
Example of sending an ArrayBuffer object.
// Sending canvas ImageData as ArrayBuffer var img = canvas_context.getImageData(0, 0, 400, 320); var binary = new Uint8Array(img.data.length); for (var i = 0; i < img.data.length; i++) { binary[i] = img.data[i]; } ws.send(binary.buffer);
4.7 webSocket.bufferedAmount
A property of the instance object bufferedAmount
that indicates how many bytes of binary data remain unsent. It can be used to determine whether the transmission is over.
var data = new ArrayBuffer(10000000); socket.send(data); if (socket.bufferedAmount === 0) { // 发送完毕 } else { // 发送还没结束 }
4.8 webSocket.onerror
Attribute of the instance object onerror
, used to specify the callback function when an error is reported.
socket.onerror = function(event) { // handle error event }; socket.addEventListener("error", function(event) { // handle error event });
Five, the realization of the server
For implementations of WebSocket servers, see Wikipedia for a list .
There are three commonly used Node implementations.
For specific usage, please check their documentation, which is not described in detail here.
6. WebSocketd
Next, I want to recommend a very special WebSocket server: Websocketd .
Its biggest feature is that the background script is not limited to languages, the standard input (stdin) is the input of WebSocket, and the standard output (stdout) is the output of WebSocket.
For example, here is a Bash script counter.sh
.
#!/bin/bash echo 1 sleep 1 echo 2 sleep 1 echo 3
Running this script on the command line will output 1, 2, and 3 with a 1 second interval between each value.
$ bash ./counter.sh 1 2 3
Now, start websocketd
, specifying this script as a service.
$ websocketd --port=8080 bash ./counter.sh
The above command will start a WebSocket server with port 8080
. Whenever a client connects to this server, the counter.sh
script is executed and its output is pushed to the client.
var ws = new WebSocket('ws://localhost:8080/'); ws.onmessage = function(event) { console.log(event.data); };
The above is the client-side JavaScript code, which will output 1, 2, and 3 in the console after running.
With it, you can easily send the output of the command line to the browser.
$ websocketd --port=8080 ls
The above command will execute the ls
command to send the contents of the current directory to the browser. Using this method to monitor the server in real time is a breeze ( code ).
For more usage, please refer to the official example .
- Example of Bash script reading client input
- Five lines of code to implement a simplest chat server
The essence of websocketd is the WebSocket proxy of the command line. As long as the program can be executed by the command line, it can communicate with the browser through WebSocket. Below is a Node implementation of the echo service greeter.js
.
process.stdin.setEncoding('utf8'); process.stdin.on('readable', function() { var chunk = process.stdin.read(); if (chunk !== null) { process.stdout.write('data: ' + chunk); } });
The command to start this script is as follows.
$ websocketd --port=8080 node ./greeter.js
The official repository has examples in various other languages .
7. Reference link
- How to Use WebSockets
- WebSockets - Send & Receive Messages
- Introducing WebSockets: Bringing Sockets to the Web
(over)