websocket解析
什么是websocket
- WebSocket是HTML5下一种新的协议(websocket协议本质上是一个基于tcp的协议)
- 它实现了浏览器与服务器全双工通信,能更好的节省服务器资源和带宽并达到实时通讯的目的
- Websocket是一个持久化的协议
websocket的原理
- websocket约定了一个通信的规范,通过一个握手的机制,客户端和服务器之间能建立一个类似tcp的连接,从而方便它们之间的通信
- 在websocket出现之前,web交互一般是基于http协议的短连接或者长连接
- websocket是一种全新的协议,不属于http无状态协议,协议名为”ws”
websocket与http的关系
相同点:
- 都是基于tcp的,都是可靠性传输协议
- 都是应用层协议
不同点:
- WebSocket是双向通信协议,模拟Socket协议,可以双向发送或接受信息
- HTTP是单向的
- WebSocket是需要浏览器和服务器握手进行建立连接的
- http是浏览器发起向服务器的连接,服务器预先并不知道这个连接
联系
WebSocket在建立握手时,数据是通过HTTP传输的。但是建立之后,在真正传输时候是不需要HTTP协议的
总结
- 首先,客户端发起http请求,经过3次握手后,建立起TCP连接;http请求里存放WebSocket支持的版本号等信息,如:Upgrade、Connection、WebSocket-Version等;
- 然后,服务器收到客户端的握手请求后,同样采用HTTP协议回馈数据;
- 最后,客户端收到连接成功的消息后,开始借助于TCP传输信道进行全双工通信。
JS 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 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135
| import Store from "@/store"; class WebSocketClass { url; protocols; ws; isReconnectionLoading = false; timeId = null; isCustomClose = false; errorStack = [];
constructor(url, protocols) { this.url = url; this.protocols = protocols; this.createWs(); }
createWs() { if ("WebSocket" in window) { this.ws = new WebSocket(this.url, this.protocols); this.onopen(); this.onerror(); this.onclose(); this.onmessage(); } else { console.log("你的浏览器不支持 WebSocket"); } }
onopen() { this.ws.onopen = () => { console.log("onopen"); this.errorStack.forEach((message) => { this.send(message); }); this.errorStack = []; this.isReconnectionLoading = false; }; }
onerror() { this.ws.onerror = (err) => { console.log(err, "onerror"); this.reconnection(); this.isReconnectionLoading = false; }; }
onclose() { this.ws.onclose = () => { console.log("onclose");
if (this.isCustomClose) return;
this.reconnection(); this.isReconnectionLoading = false; }; }
onmessage() { this.ws.onmessage = (event) => { try { Store.dispatch("user/setData", event.data); } catch (error) { console.log(error, "error"); } }; }
isConnection() { if (this.ws && this.ws.readyState === WebSocket.OPEN) return true else return false }
reconnection() { if (this.isReconnectionLoading) return;
this.isReconnectionLoading = true; clearTimeout(this.timeId); this.timeId = setTimeout(() => { this.createWs(); }, 100); }
send(message) { if (this.ws.readyState !== 1) { this.errorStack.push(message); return; }
this.ws.send(message); }
close() { this.isCustomClose = true; this.ws.close(); }
start() { this.isCustomClose = false; this.reconnection(); }
destroy() { this.close(); this.ws = null; this.errorStack = null; } }
export default WebSocketClass;
|