WebSocket-network communication protocol

你越是认真生活,你的生活就会越美好——Frank Lloyd Wright
"The Fruit of Life" Classic Quotations

1. Why do we need WebSocket?

WebSocket is a network communication protocol, and many advanced functions require it.
This article describes how to use the WebSocket protocol.

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 there is a HTTP protocol 缺陷: 通信只能由客户端发起.

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.

This 单向请求feature is destined 服务器有连续的状态变化to be very troublesome if the client wants to know. We can only use " 轮询": every time a query is sent 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 on, or the HTTP connection is always open). Therefore, engineers have been thinking about whether there is a better way. WebSocketThat's how it was invented.

2. Introduction

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

It 最大特点is, 服务器can 主动向客户端推送信息, 客户端can 主动向服务器发送信息, is truly 双向平等对话a part of the 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. 默认端口It is 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) The 没有同源限制client can communicate with any server.
  • (6) The protocol identifier is ws(if encryption was wss), 服务器网址that is 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.");
}; 

Insert picture description here

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

readyStateProperties return 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 you can communicate.
  • 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 onopenproperties of the instance object are 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 onmessageproperties of the instance object are 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 server data may be text or binary data ( blobobject or Arraybufferobject).

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 type of data received, binaryTypeattributes can also be used to explicitly specify the type of binary data received.

// 收到的是 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()methods of the instance object are 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 bufferedAmountattribute 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 onerrorproperties of the instance object are 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

There are three commonly used Node implementations for the implementation of WebSocket server.

Six, practice

Client code

Initiate requests in Google and Firefox respectively to simulate a multi-person connection. The client request will send the userAgent of the current browser, and the server will return it to all online clients after receiving it.

// 客户端代码 vue
  mounted() {
    
    
  	this.initWebsocket()
  },
  beforeDestroy() {
    
    
    this._ws.close()
  },
  methods: {
    
    
    initWebsocket() {
    
    
    // websocket请求地址 参数通过url提交
      const ws = new WebSocket(`ws://192.168.1.166:3036/activityList?id=60111d5818d04240382&name=陈坚泓`)
      this._ws = ws
      ws.onopen = () => {
    
    
        this._ws.send(window.navigator.userAgent)
      }
      ws.onmessage = e => {
    
    
        console.log(`ws.onmessage = e =>   e.data:`)
        console.log(e.data)
      }
    },
  }

Server code

// node
const WebSocket = require('ws');
const url = require('url')
const querystring = require('querystring')

module.exports = async app => {
    
    
  const wss = new WebSocket.Server({
    
     port: 3036 });
  let data = {
    
    }
  wss.on('connection', async (ws, req) => {
    
    
    console.log('websocket 连接成功的回调')
    let {
    
     query, pathname } = url.parse(req.url) || {
    
    }
    console.log('query:')
    console.log(query)
    console.log(`pathname:`)
    console.log(pathname)
    pathname = pathname.substring(1)
    query = querystring.parse(query)
    // 接收消息
    ws.on('message', msg => {
    
    
      console.log(`websocket 接收到信息的回调`)
      console.log(msg) 
      // 谷歌浏览器发起请求时 msg内容: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.102 Safari/537.36
      // 火狐浏览器发起请求时 msg内容: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:85.0) Gecko/20100101 Firefox/85.0
      wss.clients.forEach(function each(client) {
    
    
        console.log(`client.readyState: ${
      
      client.readyState}`) // client.readyState: 1
        if (client.readyState === WebSocket.OPEN) {
    
    
          data.note = `服务端返回的内容`
          data.message = msg
          client.send(JSON.stringify(data));
        }
      });

    });
    ws.on('close', () => {
    
    
      console.log(`websocket 关闭时的回调`)
    })
  });
}

Insert picture description here

Insert picture description here
Insert picture description here


谢谢你阅读到了最后~
期待你关注、收藏、评论、点赞~
让我们一起 变得更强


PS:
This article is reproduced in WebSocket Tutorial-Ruan Yifeng

Liao Xuefeng's official website
HTML5 WebSocket-Novice Tutorial

Guess you like

Origin blog.csdn.net/weixin_42752574/article/details/113279388