1, 背景
很多网站为了实现推送技术, 所用的技术都是 Ajax 轮询. 轮询是在特定的的时间间隔由浏览器对服务器发出 HTTP 请求, 然后由服务器返回最新的数据给客户端的浏览器. 这种传统的模式带来很明显的缺点, 即浏览器需要不断的向服务器发出请求, 然而 HTTP 请求可能包含较长的头部, 其中真正有效的数据可能只是很小的一部分, 显然这样会浪费很多的带宽等资源. html5 新增的一些新协议 webSocket, 可以提供在单个 TCP 连接上提供全双工, 双向通信, 能够节省服务器资源和带宽, 并且能够实时进行通信.
2,WebSocket 介绍
传统的 http 也是一种协议, WebSocket 是一种协议, 使用 http 服务器无法实现 WebSocket,
2.1. 浏览器支持情况
基本主流浏览器都支持
2.2. 优点
相对于 http 有如下好处:
1. 客户端与服务器只建立一个 TCP 连接, 可以使用更少的连接.
2.WebSocket 服务器端可以主动推送数据到客户端, 更灵活高效.
3. 更轻量级的协议头, 减少数据传送量.
对比轮训机制
3,WebSocket 用法
我们了解 WebSocket 是什么, 有哪些优点后, 怎么使用呢?
3.1.WebSocket 创建
WebSocket 使用了自定义协议, url 模式与 http 略有不同, 未加密的连接是 ws://, 加密的连接是 wss://,WebSocket 实例使用 new WebSocket() 方法来创建,
var ws = new WebSocket(url, [protocol] );
第一个参数 url, 指定连接的 URL. 第二个参数 protocol 是可选的, 指定了可接受的子协议.
3.2.WebSocket 属性
当创建 ws 对象后, readyState 为 ws 实例状态, 共 4 种状态
0 表示连接尚未建立.
1 表示连接已建立, 可以进行通信.
2 表示连接正在进行关闭.
3 表示连接已经关闭或者连接不能打开.
Tips: 在发送报文之前要判断状态, 断开也应该有重连机制.
3.3.WebSocket 事件
在创建 ws 实例对象后, 会拥有以下几个事件, 根据不同状态可在事件回调写方法.
ws.onopen 连接建立时触发
ws.onmessage 客户端接收服务端数据时触发
ws.onerror 通信发生错误时触发
ws.onclose 连接关闭时触发
- ws.onmessage = (res) => {
- console.log(res.data);
- };
- ws.onopen = () => {
- console.log('OPEN...');
- };
- ws.onclose=()=>{
- console.log('CLOSE...');
- }
3.4.WebSocket 方法
ws.send() 使用连接发送数据 (只能发送纯文本数据)
ws.close() 关闭连接
4,Demo 演示
了解 WebSocket 的一些 API 之后, 趁热打铁, 做一个小案例跑一下.
4.1.Node 服务器端
WebSocket 协议与 Node 一起用非常好, 原因有以下两点:
1.WebSocket 客户端基于事件编程与 Node 中自定义事件差不多.
2.WebSocket 实现客户端与服务器端长连接, Node 基本事件驱动的方式十分适合高并发连接
创建一个 webSocket.JS 如下:
- const WebSocketServer = require('ws').Server;
- const wss = new WebSocketServer({ port: 8080 });
- wss.on('connection', function (ws) {
- console.log('client connected');
- ws.on('message', function (message) {
- ws.send('我收到了' + message);
- });
- });
打开 Windows 命令窗口运行
4.2.HTML 客户端
新建一个 index.HTML 页面
- <!DOCTYPE HTML>
- <HTML lang="en">
- <head>
- <meta charset="UTF-8">
- <title>webSocket 小 Demo</title>
- </head>
- <body>
- <div class="container">
- <div>
- <input type="text" id="msg">
- <button onclick="sendMsg()"> 发送报文 </button>
- </div>
- </div>
- <script>
- const ws = new WebSocket('ws://localhost:8080');
- ws.onmessage = (res) => {
- console.log(res);
- };
- ws.onopen = () => {
- console.log('OPEN...');
- };
- ws.onclose = () => {
- console.log('CLOSE...');
- }
- function sendMsg() {
- let msg = document.getElementById('msg').value;
- ws.send(msg);
- }
- </script>
- </body>
打开浏览器依次输入字符 1,2,3, 每次输入完点击发送报体, 可见在 ws.onmessage 事件中 res.data 中返回来我们发的报文
5, 问题与总结
以上只是简单的介绍了下 WebSocket 的 API 与简单用法, 在处理高并发, 长连接这些需求上, 例如聊天室, 可能 WebSocket 的 http 请求更加合适高效.
但在使用 WebSocket 过程中发现容易断开连接等问题, 所以在每次发送报文前要判断是否断开, 当多次发送报文时, 由于服务器端返回数据量不同, 返回客户端前后顺序也不同, 所以需要在客户端收到上一个报文返回数据后再发送下一个报文, 为了避免回调嵌套过多, 通过 Promise ,async ,await 等同步方式解决. 关于 WebSocket 就写这么多, 如有不足, 欢迎多多指正!
参考资料:
《JavaScript 高级教程》
《深入检出 Node.JS》
《菜鸟教程》 https://www.runoob.com/
来源: https://www.cnblogs.com/peerless1029/p/11909446.html