jeremygo

jeremygo

我是把下一颗珍珠串在绳子上的人

WebSocket 实践

做小程序项目的时候有实时通信的需求,这里就整理一下 WebSocket 的知识

关于 WebSocket#

  • 前言:Web 应用的信息交互过程一般是客户端通过浏览器发出一个请求,服务器端接收完请求后进行处理并且返回结果给客户端,然后客户端浏览器解析信息,这样的机制对于实时要求比较高的应用来说就有很大的受限了,因此需要有一种高效节能的双向通信机制来保证数据的实时传输,WebSocket 应运而生
  • 概念:
    • MDN: WebSocket 是一个可以创建和服务器间进行双向会话的高级技术,通过这个 API 你可以向服务器发送消息并接受基于事件驱动的响应,这样就不用向服务器轮询获取数据了
    • WebSocket 有 web TCP 之称,顾名思义是用来通信的,作为 HTML5 中新增的一种通信协议,由 TCP 协议与编程 API 组成,可以在浏览器与服务器之间建立双向连接,以基于事件的方式,赋予浏览器原生的实时通信能力,从而扩展我们的 web 应用,提升应用性能与用户体验
  • 为什么使用:
    在 WebSocket 出现之前有一些其它的实时通讯方案,比如轮询、长轮询、服务器发送事件
    • 轮询 (Polling):客户端以一定的时间间隔向服务器发送请求,通过频繁请求的方式来保持客户端和服务器端的数据同步。通常采取setInterval或者setTimeout实现。问题:客户端以固定频率向服务器端发送请求时,服务器端的数据可能并没有更新,这样很多请求就是没有必要的,浪费带宽,低效率
    • 长轮询 (Long Polling):对定时轮询的改进和提高,当服务器端没有数据更新的时候,连接会保持一段时间周期直到数据或状态改变或者时间过期,以此减少无效的客户端与服务器间的交互。问题:如果服务端的数据变更非常频繁的话,与定时轮询比较起来没有本质上性能的提高
    • 服务器发送事件 (Server-Sent Event):是 HTML5 规范的一个组成部分,可以实现服务器到客户端的单向数据通信,通过 SSE,客户端可以自动获取数据更新,而不用重复发送 HTTP 请求。问题:只支持到服务器到客户端单向的事件推送,而且所有版本的 IE 都不支持 SSE
    • WebSocket:在流量与负载量增大的情况下,相比于传统的 Ajax 轮询方案有极大的性能优势,在开发方面也不算复杂,只需要实例化 WebSocket 创建连接,成功后就可以发送相应消息了

Node 实现#

这里采用 Node 的 ws 库来实现简单的 WebSocket 服务器

  • 服务器:
var WebSocketServer = require("ws").Server;
var wss = new WebSocketServer({
    port: 3001
});

wss.on("connection", function(ws) {
    ws.on("message", function(msg) {
        console.log(msg);
        ws.send("Nice to meet you!");
    });
    ws.on("close", function() {
        console.log("Stop client");
    });
});
  • 小程序客户端:
wx.connectSocket({
    url: '服务器的链接:3001',
    data: {},
    header: {
        'content-type': 'application/json'
    },
    method: 'GET',
    success: function() {
        console.log("客户端连接成功");
    }
}),
wx.onSocketOpen(function() {
    console.log("WebSocket连接已打开");
    wx.sendSocketMessage({
        data: 'Hello!'
    });
}),
wx.onSocketMessage(function(msg) {
    console.log("接收到:"+ msg);
});

这里特别提一下wx.onSocketMessage(),因为它只接收字符串和二进制类型的数据,因此如果需要发送 json 格式的数据就需要转换一下,只要是支持 WebSocket 肯定支持原生 window.JSON,所以可以直接使用 JSON.parse () 和 JSON.stringify () 来转换

这样一个双向通信的实例基本就完成了

加载中...
此文章数据所有权由区块链加密技术和智能合约保障仅归创作者所有。