[webSocket]WebSocket tutorial

WebSocket is a network communication protocol, and many advanced functions require it.

This article describes how to use the WebSocket protocol.

1. Why do we need WebSocket?

People who are new to WebSocket will ask 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: the communication can only be initiated by the client.

For example, if we want to know today's weather, we can only ask the client to send a request to the server, and the server returns the query result. The HTTP protocol cannot enable the server to actively push information to the client.

Insert picture description here

The characteristic of this one-way request is 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, we will send out a query to find out if the server has new information. The most typical scenario is a chat room.

Polling is inefficient and wastes resources (because the connection must be kept connected or the HTTP connection is always open). Therefore, engineers have been thinking about whether there is a better way. This is how WebSocket was invented.

2. Introduction

The WebSocket protocol was born in 2008 and became an international standard in 2011. All browsers are already supported.

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 true two-way equal dialogue and belongs to a type of server push technology.
Insert picture description here

Other features include:

(1) Based on the TCP protocol, the server-side implementation is relatively easy.

(2) It has good compatibility with 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 block 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) You can send text or binary data.

(5) There is no homology restriction, and the client can communicate with any server.

(6) The protocol identifier is ws (if encrypted, it is wss), and the server website is the URL.

ws://example.com:80/some/path

Insert picture description here

Three, a simple example of the client

The usage of WebSocket is quite 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's 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 with the server.

For a list of all the properties and methods of the instance object, see here.

4.2 webSocket.readyState

The readyState property returns the current state of the instance object, there are four types.

  • CONNECTING: The value is 0, which means it is connecting.
  • OPEN: The value is 1, which means the connection is successful and communication is possible.
  • CLOSING: The value is 2, which means the connection is being closed.
  • CLOSED: The value is 3, which means the connection has been closed or failed to open the connection.
    The following 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

The onopen attribute of the instance object is used to specify the callback function after a successful connection.

ws.onopen = function () {
    
    
  ws.send('Hello Server!');
}

If you want to specify multiple callback functions, you can use the addEventListenermethod.

ws.addEventListener('open', function (event) {
    
    
  ws.send('Hello Server!');
});

4.4 webSocket.onclose

The onclose attribute of the instance object is 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

The onmessage attribute of the instance object is used to specify the callback function after receiving the server data.

ws.onmessage = function(event) {
    
    
  var data = event.data;
  // 处理数据
};

ws.addEventListener("message", function(event) {
    
    
  var data = event.data;
  // 处理数据
});

Note that the 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 determining the received data type, you can also use the binaryType attribute 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 send() method of the instance object is 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 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

The bufferedAmount property of the instance object indicates how many bytes of binary data have not been sent. 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

The onerror attribute of the instance object is 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 the implementation of the WebSocket server, you can check the list on Wikipedia.

There are three commonly used Node implementations as follows.

Six, WebSocketd

Next, I would like 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.
Insert picture description here

For example, the following 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 an interval of 1 second between each value.

$ bash ./counter.sh
1
2
3

Now, start websocketdand specify 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, it will execute the counter.sh script and push its output to the client.

var ws = new WebSocket('ws://localhost:8080/');

ws.onmessage = function(event) {
    
    
  console.log(event.data);
};

The above is the JavaScript code of the client. After running, it will output 1, 2, and 3 in the console.

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 simply a breeze (code).

Insert picture description here

For more usage, please refer to the official example.

Insert picture description here
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. The following is an echo service implemented by Node 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

Guess you like

Origin blog.csdn.net/u013034585/article/details/106346498