1. 什么是websocket?看看官方的解释:
WebSocket是一种通信协议,可在单个TCP连接上进行全双工通信。WebSocket使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据。在WebSocket API中,浏览器和服务器只需要完成一次握手,两者之间就可以建立持久性的连接,并进行双向数据传输。
?太复杂了?那就抓住几关键词就行了:双向通信,基于HTML5,所有浏览器在2011年都支持了。
还是不太明白?上几张图领悟领悟:
![](https://img-blog.csdnimg.cn/20210726221638308.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQyMjMxMTU2,size_16,color_FFFFFF,t_70) wss是ws的加密。![](https://img-blog.csdnimg.cn/20210726221638214.png)
文字再来一遍websocket的特点:
(1)建立在TCP上,持久化连接。
(2)与http/https有较好兼容。
(3)通信高效。
(4)支持文本和二进制传输数据。
(5)没有同源限制,客户端可用与任意服务器通信。
(6)协议符:ws。加密版:wss。
拓展:
axios轮询:即服务端定时向客户端发送请求获取数据。
长轮询:是客户端和浏览器保持一个长连接,等服务端有消息返回,断开。然后再重新连接,然后循环反复。
客户端发起一个长轮询,服务端如果没有数据要返回的话,会hold住请求,等到有数据,就会返回给客户端,然后循环反复。
axios轮询和长轮询:都存在性能消耗大的问题。
websocket请求头request headers:
Connection: Upgrade //表示要升级协议
Sec-WebSocket-Extensions: permessage-deflate; client_max_window_bits
Sec-WebSocket-Version: 13 //表示websocket的版本。如果服务端不支持该版本,需要返回一个Sec-
WebSocket-Versionheader,里面包含服务端支持的版本号。
Upgrade: websocket //要升级协议到websocket协议
Sec-WebSocket-Key: bwb9SFiJONXhQ/A4pLaXIg== //对应服务端响应头的Sec-WebSocket-Accept,由于没
有同源限制,websocket客户端可任意连接支持
websocket的服务。这个就相当于一个钥匙一把锁,避免多余的,无意义的连接。
websocket响应头response headers:
Connection: Upgrade
Sec-WebSocket-Accept: 2jrbCWSCPlzPtxarlGTp4Y8XD20= //用来告知服务器愿意发起一个websocket连接, 值根据客户端请求头的Sec-WebSocket-Key计算出来
Upgrade: websocket
2. 讲了这么概念,那么 怎么用?
? ? ? ? 2.1 客户端使用websocket:基于2011年基本浏览器都支持HTML5的websocket。
const ws = new WebSocket("ws://127.0.0.1:8080")
ws.onopen = e => {
// 连接后监听ws.readyState返回0,1,2,3分别表示连接中,连接成功,即将关闭,关闭后
console.log(`WebSocket 连接状态: ${ws.readyState}`)
}
ws.onmessage = data => {
// 当服务端返回数据的时候
}
ws.onclose = data => {
// 监听连接关闭
}
ws.onerror = err => {
// 监听连接错误
}
// 点击发送按钮。将数据发送给服务端
ws.send('发送给服务端的数据')
// 客户端主动关闭连接
ws.close()
? ? ? ? 2.2 服务端使用websocket:使用第三方模块,如require('ws'),require('express-ws'),require('socket.io'),require('websocket').....
? ? ? ? ? ? ? ? 2.2.1 基于ws模块:
const app = require('express')();
const server = require('http').Server(app);
const WebSocket = require('ws');
const ws= new WebSocket.Server({ port: 8080 });
ws.on('connection', (connection)=> {
connection.on('message', (msg) =>{
//接收到服务端的消息
});
connection.send('消息');
});
app.get('/', (req, res) =>{
res.body='首页';
});
app.listen(3000);
? ? ? ? ? ? ? ? 2.2.2 基于socket.io模块:https://github.com/socketio/socket.io。兼容http,koa,express,fastify.....
npm install socket.io
// http版
const server = require('http').createServer();
const io = require('socket.io')(server);
io.on('connection', client => {
client.on('event', data => { });
client.on('disconnect', () => { });
});
server.listen(3000);
// 独立版
const io = require('socket.io')();
io.on('connection', client => { });
io.listen(3000);
//express版
const app = require('express')();
const server = require('http').createServer(app);
const io = require('socket.io')(server);
io.on('connection', () => { });
server.listen(3000);
// koa版
const app = require('koa')();
const server = require('http').createServer(app.callback());
const io = require('socket.io')(server);
io.on('connection', () => { });
server.listen(3000);
//fastify版
const app = require('fastify')();
app.register(require('fastify-socket.io'));
app.io.on('connection', () => { /* … */ });
app.listen(3000);
? ? ? ? ? ? ? ? 2.2.3 基于websocket:
npm install websocket
const WebSocketServer = require('websocket').server;
const http = require('http');
const app = http.createServer();
app.listen(8080);
const ws = new WebSocketServer({
httpServer: app,
autoAcceptConnections:false
});
ws.on('request', (request) => {
const connection = request.accept('echo-protocol', request.origin);
connection.on('message', (msg) => {
console.log('message');
if (msg.type === 'utf8') {
connection.sendUTF(msg.utf8Data);
} else if (msg.type === 'binary') {
connection.sendBytes(msg.binaryData);
}
})
connection.on('close', () => {
console.log('close');
})
})
参考:https://www.cnblogs.com/chyingp/p/websocket-deep-in.html
|