1

一.什么是WebSocket

  WebSocket 是 HTML5 开始提供的一种在单个 TCP 连接上进行全双工(full-duplex)通讯的协议。没有了 Request 和 Response 的概念,两者地位完全平等,连接一旦建立,就建立了真持久性连接,双方可以通过WebSocket随时向对方发送数据。

WebSocket有如下特性:

  • 伴随着HTML5而出现
  • Web端的Socket, 服务器端和客户端可相互发送消息
  • 本质上是TCP连接
  • 为解决客户端与服务端实时通信而产生的技术
    注:WebSocket长连接需要基于Ping/Pong心跳机制来维持。

现有的用于服务器和客户端之间的双工通信技术:

  • 轮询(Polling):
      客户端每隔固定时间向后台发送一次请求,询问服务器是否有新数据。
    缺点:
    1.延迟,需要固定的轮询时间,不一定是实时数据。
    2.大量耗费服务器内存和宽带资源,因为不停的请求服务器,很多时候 并没有新的数据更新,因此绝大部分请求都是无效请求。
  • 长轮询(Long Polling):
      客户端发送 HTTP 给服务器之后,有没有新消息,如果没有新消息,就一直等待。直到有消息或者超时了,才会返回给客户端。消息返回后,客户端再次建立连接,如此反复。
    优点:在某种程度上减小了网络带宽和 CPU 利用率等问题。
    缺点:
    1.如果是高实时的系统,肯定不会采用这种办法。因为一个 GET 请求来回需要 2个 RTT,很可能在这段时间内,数据变化很大,客户端拿到的数据已经延后很多了。
    2.网络带宽低利用率的问题也没有从根源上解决。每个 Request 都会带相同的 Header。
    注:
    RTT(Round-Trip Time): 往返时延。在计算机网络中它是一个重要的性能指标,表示从发送端发送数据开始,到发送端收到来自接收端的 确认(接收端收到数据后便立即发送确认),总共经历的时延RTT(Round-Trip Time): 往返时延。在计算机网络中它是一个重要的性能指标,表示从发送端发送数据开始,到发送端收到来自接收端的 确认(接收端收到数据后便立即发送确认),总共经历的时延。
  • 数据流(Streaming):
      服务器保持连接打开并与客户端一起激活,直到并且除非提取所需的数据。在这种情况下,连接是无限期打开的。
    缺点:
    1.流传输包括HTTP标头,这会增加文件大小,增加延迟。
    2.在服务器往客户端推送,这个方向的流实时性比较好。但是依旧是单向的,客户端请求服务器依然还需要一次 HTTP 请求。
  • AJAX:
      AJAX基于Javascript的 XmlHttpRequest 对象。它是Asynchronous Javascript和XML的缩写形式。XmlHttpRequest 对象允许执行Javascript而无需重新加载完整的网页。AJAX仅发送和接收网页的一部分。
    缺点:
    1.需要发送HTTP标头,这使数据量更大。
    2.是半双工的。
    3.服务器消耗更多资源

二.原生WebSocket

  WebSocket构造函数,为了建立到服务器的WebSocket连接,使用WebSocket接口,通过指向一个代表所要连接端点的URL,实例化一个WebSocket对象。

WebSocket协议定义了两种URL方案(URL Scheme):

  • ws(WebSocket):客户端与服务器之间的非加密流量,与HTTP URI方案类似。
  • wss(WebSocket Secure):客户端与服务器之间的加密流量,该方案表示使用传输层安全性(TLS,也叫SSL)的WebSocket连接,使用HTTPS采用的安全机制来保证HTTP连接安全。

  WebSocket构造函数的必须参数如下,它必须是以ws://或者wss://开始的一个完全限定URL。
如:

let ws = new WebSocket("ws://aaa.com");
//或者是
let ws = new WebSocket("ws://aaa.com", "myProtocol");
//或者是
let ws = new WebSocket("ws://aaa.com", ["myProtocol1", "myProtocol2"]);

  连接到WebSocket服务器时,可以选择使用第二个参数列出应用程序支持的协议,用于协议协商。
  协议协商对于确定WebSocket服务器支持的协议及版本很有用。应用程序可能支持多个协议,使用协议协商选择与特定服务器通信的协议。

1.WebSocket 事件

事件事件处理程序描述
openSocket.onopen连接建立时触发
messageSocket.onmessage客户端接收服务端数据时触发
errorSocket.onerror通信发生错误时触发
closeSocket.onclose连接关闭时触发

2.WebSocket 方法

方法描述
Socket.send(string)使用连接发送数据
Socket.close(number, string)关闭连接

二.插件WebSocket: socket.io(服务端)/socket.io-client(客户端)

文档地址:https://socket.io/docs/v4/cli...

客户端NPM安装:

npm install socket.io-client

客户端配置并连接服务器:

import io from "socket.io-client";
const socket = io(
        "http://aaa.com",//java后台socket server地址
        {
            reconnection: true,//是否自动重连
            reconnectionDelay: 10 * 1000,//每次重连的延迟
            timeout: 10000,//每次重连的时间间隔
            reconnectionAttempts: 100,//尝试重连次数
            //连接的协议的顺序优先级
            transports: ['websocket', 'flashsocket', 'htmlfile', 'xhr-multipart', 'xhr-polling', 'jsonp-polling']//
        });
//其余配置详见文档

客户端监听服务端传递的信息:

console.log(socket.connected); // socket是否与服务器连接
console.log(socket.disconnected); // socket是否与服务器断开连接
socket.open(); // 手动重连
// 连接成功
socket.on("connect", () => {
  console.log(socket.id, '监听客户端连接成功-connect');
})
// 断开连接
socket.on("disconnect", (reason) => {
  console.log(socket.connected);
  console.log("断开连接-disconnect", reason);
})
// 错误
socket.on("error", (err) => {
  console.log("错误-error", err);
})
// 连接错误
socket.on("connect_error", (err) => {
  err
  console.log("连接错误-connect_error");
});
// 连接超时
socket.on("connect_timeout", (data) => {
  console.log("连接超时-connect_timeout", data);
});
// 重连成功
socket.on("reconnect", (attemptNumber) => {
  // 重连尝试次数
  console.log("重连成功-reconnect", attemptNumber)
});
// 尝试重连时触发
socket.on("reconnect_attempt", (attemptNumber) => {
  // 重连尝试次数
  console.log("尝试重连-reconnect_attempt", attemptNumber)
});
// 在尝试重新连接时触发
socket.on("reconnecting", (attemptNumber) => {
  // 重连尝试次数
  console.log("正在尝试重连-reconnecting", attemptNumber)
});
// 重连尝试错误
socket.on("reconnect_error", (err) => {
  err
  console.log(socket.connected);
  console.log("重连尝试错误-reconnect_error");
});
// 客户端不能重连时触发
socket.on("reconnect_failed", () => {
  console.log("客户端不能连接-reconnect_failed")
});
// 当一个ping被发送到服务器时触发
socket.on("ping", () => {
  console.log("一个ping发送到服务器-ping")
});

// 当服务器收到pong时触发
socket.on("pong", (data) => {
  // data: 延迟多少ms
  console.log("服务器收到pong-pong", data);
});

客户端向服务端socket发送信息:

socket.emit("eventName", msg, handler)//handler回调可以接受到服务端返回的结果

爱吃鸡蛋饼
55 声望8 粉丝