WebSocket
WebSsocket和Ajax
打个比方,时不时要去服务器查看一下有没有新的留言。
用ajax
只能搞个定时器,时不时去请求一下看看有没有新的留言,也就是轮询。这种方式缺点是
1.浪费服务器资源,因为要不停的连接,断开,请求。
2.浪费带宽资源,如果是移动端的应用,流量是要钱的,更死人了。
所以ajax不适合现在移动互联网的需求。
用websocket
- 性能高,比普通ajax大概高2-10倍左右
普通的http通信是基于字符的通信,所谓超文本,还是文本。而websocket一开始是文本,但一旦连接建立了,协议升级完成了,会是一个二进制的一个协议,无需对数据做什么转换之类的,这是性能高的原因之一。 - 双向通信
不需要你去请求,只要连上了等着就行,等有数据了服务器会主动找你。这是websocket最大的优点。还是基于http,在建立连接的阶段,还是通过普通的http协议来交换信息。 - 直接跨域
socket.io
cnpm i socket.io -D
- 简单方便
- 兼容1e5
- 自动帮助你对数据进行解析
1 | //html |
原生websocket
network里websocket请求头里会有这几个东西1
2
3
4
5
6
7
8//一个扩展信息,可忽略
Sec-WebSocket-Extensions: permessage-deflate; client_max_window_bits
// 验证是不是websocket
Sec-WebSocket-Key: ydOb9ivgNMpZk0zNiobpfQ==
// websocket版本,不同版本验证是有差异的
Sec-WebSocket-Version: 13
//协议升级
Upgrade: websocket
连接建立阶段实现:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84 //html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<script>
let ws = new WebSocket('ws://localhost:8081/');
//并不是连接上就会触发,交换数据后会触发
ws.onopen=function(){
console.log('连接已建立');
};
//当有消息
ws.onmessage=function(){};
//当连接关闭
ws.onclose=function(){};
//当异常关闭
ws.onerror=function(){};
</script>
</head>
<body>
</body>
</html>
// js
//二进制,实际上websocket就是tcp连接,所以需要net
const net = require('net');
const crypto = require('crypto');
function parseHeader(str){
let arr = str.split('\r\n').filter(line=>line);
arr.shift();
let headers={}
arr.forEach(line => {
let [name,value]=line.split(':');
name=name.replace(/^\s+|\s+$/g,'').toLowerCase();
value=value.replace(/^\s+|\s+$/g,'');
headers[name]=value;
});
return headers;
}
//参数是一个原始的sock对象
let server = net.createServer(sock=>{
//第一次握手接到的数据
sock.once('data',buffer=>{
let str = buffer.toString();
let headers=parseHeader(str);
if(headers['upgrade']!='websocket'){
console.log('no upgrade');
sock.end();
}else if(headers['sec-websocket-version']!='13'){
console.log('no 13');
sock.end();
}else{
//1.key : 从http的头里来
//2.uuid : '258EAFA5-E914-47DA-95CA-C5AB0DC85B11' //作者定的,固定的。
//3.result => base64(sha1(key + uuid))
let key = headers['sec-websocket-key'];
let uuid = '258EAFA5-E914-47DA-95CA-C5AB0DC85B11';
//创建一个hash对象,签名算法是sha1
let hash = crypto.createHash('sha1');
hash.update(key + uuid);
let key2 = hash.digest('base64');
sock.write(`HTTP/1.1 101 Switching Protocols\r\nUpgrade:websocket\r\nConnection:upgrade\r\nSec-Websocket-Accept:${key2}\r\n\r\n`);
}
})
sock.on('end',()=>{
})
});
server.listen(8081);