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. WebSocket
That'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.
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 waswss
),服务器网址
that isURL
.
ws://example.com:80/some/path
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
readyState
Properties 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 onopen
properties 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 addEventListener
method.
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
properties 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 ( 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 type of data received, binaryType
attributes 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 bufferedAmount
attribute 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
properties 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 关闭时的回调`)
})
});
}
谢谢你阅读到了最后~
期待你关注、收藏、评论、点赞~
让我们一起 变得更强
PS:
This article is reproduced in WebSocket Tutorial-Ruan Yifeng
Liao Xuefeng's official website
HTML5 WebSocket-Novice Tutorial