WebSocket

2019-09-25  本文已影响0人  糖糖不加糖_

一、定义

WebSocket是一种网络传输协议,可在单个TCP连接上进行全双工通信(又称为双向同时通信,即通信的双方可以同时发送和接受信息的信息交互方式),与HTTP协议同属于应用层协议。

二、背景

传统模式实现推送所用技术为轮询,即在特定的时间间隔中,浏览器对服务器发送送HTTP请求,服务器返回最新的数据给客户端浏览器。这样有一个明显的缺点,HTTP请求可能包含较长的头部,其中真正有效的数据可能只是很小的一部分,这样会消耗很多带宽资源。
WebSocket使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据。在WebSocket API中,浏览器和服务器只需要完成一次HTTP握手,两者之间就可以创建持久性的连接,并进行双向数据传输。

HTTP和WebSocket对比图.png

三、特点

四、网络七层协议

网络七层协议从上到下依次为:

其中前四层定义了应用程序的功能,后三层主要面向通过网络的端到端的数据流

五、WebSocket数据处理

WebSocket是通过事件通知的方式运行的。它包含四个事件和两个动作(发送和关闭

主要属性(事件)

方法(动作)

使用

创建一个链接

浏览器发起的ws请求,可以看到和HTTP请求长的是非常相似的。但是,它只是请求阶段长得像而已,下面是一个HTTP请求头和一个WebSocket请求头:

HTTP请求头.png WebSocket请求头.png

请求的地址,一般是:ws://***,或者是使用了SSL/TLS加密的安全协议wss:,用来标识是WebSocket请求。

建立连接.png

断连问题

客户端与服务器端连接后,一旦长时间没有通信,当服务器资源紧张的时候会优先断开websocket不活跃的连接,此时需要做一个心跳检测,使得客户端与服务器端能正常保持着连接状态,即便在断网等外在因素影响下断开后也能正常保持连接状态


interface HeartCheckInfo {
  timeout: number;
  timeoutObj: number | undefined;
  serverTimeoutObj: number | undefined;
  start: () => void;
}

let ws: WebSocket | null = null;
let url: string = '';
let isConnect: boolean = false;
let conTimer: number | undefined = undefined;
let handleData: (data: string) => void = () => {};

const createWebSocket = (wsUrl: string, callback: (data: string) => void) => {
  url = wsUrl;
  handleData = callback;
  try {
    if ('WebSocket' in window) {
      ws = new WebSocket(url);
    } else {
      // 提示不支持websocket
      console.log('不支持websocket')
    }
    handleEvent();
  } catch(e) {
    reconnect();
    console.log(e);
  }
}

const handleEvent = () => {
  if (ws) {
    ws.onclose = () => {
      reconnect();
      // console.log('连接关闭');
    };
    ws.onerror = () => {
      reconnect();
      // console.log('连接错误');
    };
    ws.onopen = () => {
      // 重置心跳值
      heartCheck.start();
      console.log('开始接收消息');
    };
    ws.onmessage = (event) => {
      // 重置心跳值
      heartCheck.start();
      const { data } = event
      handleData(data);
    }
  }
}

const reconnect = () => {
  if (isConnect) return;
  isConnect = true;
  //没连接上会一直重连,设置延迟避免请求过多
  conTimer && clearTimeout(conTimer);
  conTimer = window.setTimeout(() => {
    createWebSocket(url, handleData);
    isConnect = false;
  }, 2000);
}

const heartCheck: HeartCheckInfo = {
  timeout: 30001,
  timeoutObj: undefined,
  serverTimeoutObj: undefined,
  start(){
    const self = this;
    self.timeoutObj && clearTimeout(self.timeoutObj);
    self.serverTimeoutObj && clearTimeout(self.serverTimeoutObj);
    self.timeoutObj = window.setTimeout(() => {
      //这里发送一个心跳,后端收到后,返回一个心跳消息,
      ws && ws.send('心跳值');
      // 服务器关闭
      self.serverTimeoutObj = window.setTimeout(() => {
        console.log(ws);
        ws && ws.close();
      }, self.timeout);
    }, self.timeout)
  }
}

Q&A

Socket与WebSocket是否相等?

Socket !== WebSocket

轮询与WebSocket对比

为什么WebSocket会解决服务器上消耗资源的问题
我们所用的程序是要经过两层代理的,即HTTP协议在Nginx等服务器的解析下,然后再传送给相应的Handler来处理。简单地说,我们有一个非常快速的接线员(Nginx),他负责把问题转交给相应的客服(Handler)。本身接线员基本上速度是足够的,但是每次都卡在客服(Handler)了,老有客服处理速度太慢。,导致客服不够。Websocket就解决了这样一个难题,建立后,可以直接跟接线员建立持久连接,有信息的时候客服想办法通知接线员,然后接线员在统一转交给客户。这样就可以解决客服处理速度过慢的问题了。

Websocket使用dva中的subscriptions不能在同一路由下连接多个,否则先连接的会被自动断开

上一篇 下一篇

猜你喜欢

热点阅读