WebSocket 用法

1. 什么是WebSocket?

WebSocket是一种协议,用于在Web应用程序和服务器之间建立实时、双向的通信连接。
它通过一个单一的TCP连接提供了持久化连接,这使得Web应用程序可以更加实时地传递数据。
WebSocket协议最初由W3C开发,并于2011年成为标准。

2. WebSocket的优势和劣势

WebSocket的优势包括:

实时性: 由于WebSocket的持久化连接,它可以实现实时的数据传输,避免了Web应用程序需要不断地发送请求以获取最新数据的情况。
双向通信: WebSocket协议支持双向通信,这意味着服务器可以主动向客户端发送数据,而不需要客户端发送请求。
减少网络负载: 由于WebSocket的持久化连接,它可以减少HTTP请求的数量,从而减少了网络负载。
WebSocket的劣势包括:

需要浏览器和服务器都支持: WebSocket是一种相对新的技术,需要浏览器和服务器都支持。一些旧的浏览器和服务器可能不支持WebSocket。
需要额外的开销: WebSocket需要在服务器上维护长时间的连接,这需要额外的开销,包括内存和CPU。
安全问题: 由于WebSocket允许服务器主动向客户端发送数据,可能会存在安全问题。服务器必须保证只向合法的客户端发送数据。

3. WebSocket的协议

WebSocket 协议是一种基于TCP的协议,用于在客户端和服务器之间建立持久连接,并且可以在这个连接上实时地交换数据。WebSocket协议有自己的握手协议,用于建立连接,也有自己的数据传输格式。

当客户端发送一个 WebSocket 请求时,服务器将发送一个协议响应以确认请求。在握手期间,客户端和服务器将协商使用的协议版本、支持的子协议、支持的扩展选项等。一旦握手完成,连接将保持打开状态,客户端和服务器就可以在连接上实时地传递数据。

WebSocket 协议使用的是双向数据传输,即客户端和服务器都可以在任意时间向对方发送数据,而不需要等待对方的请求。它支持二进制数据和文本数据,可以自由地在它们之间进行转换。

总之,WebSocket协议是一种可靠的、高效的、双向的、持久的通信协议,它适用于需要实时通信的Web应用程序,如在线游戏、实时聊天、仪表盘、股票行情等等。

4. WebSocket的生命周期

WebSocket 生命周期描述了 WebSocket 连接从创建到关闭的过程。一个 WebSocket 连接包含以下四个主要阶段:

连接建立阶段(Connection Establishment): 在这个阶段,客户端和服务器之间的 WebSocket 连接被建立。客户端发送一个 WebSocket 握手请求,服务器响应一个握手响应,然后连接就被建立了。
连接开放阶段(Connection Open): 在这个阶段,WebSocket 连接已经建立并开放,客户端和服务器可以在连接上互相发送数据。
连接关闭阶段(Connection Closing): 在这个阶段,一个 WebSocket 连接即将被关闭。它可以被客户端或服务器发起,通过发送一个关闭帧来关闭连接。
连接关闭完成阶段(Connection Closed): 在这个阶段,WebSocket 连接已经完全关闭。客户端和服务器之间的任何交互都将无效。
“需要注意的是,WebSocket 连接在任何时候都可能关闭,例如网络故障、服务器崩溃等情况都可能导致连接关闭。因此,需要及时处理 WebSocket 连接关闭的事件,以确保应用程序的可靠性和稳定性。

5.WebSocket的性能

1 与传统的HTTP请求/响应模型比较

  • 双向通信性能更好: WebSocket协议使用单一的TCP连接,允许客户端和服务器在同一个连接上进行双向通信。这种实时的双向通信可以更快地传输数据,而不需要建立多个HTTP请求/响应连接。
  • 更小的网络流量: 与HTTP相比,WebSocket协议需要更少的网络流量来维护连接,因为它不需要在每个请求/响应交换中发送头部信息。
  • 更低的延迟: WebSocket协议允许服务器主动向客户端推送消息,而不需要客户端先发送请求。这种实时通信可以减少响应延迟,并提高应用程序的性能。
  • 更好的服务器资源管理: 由于WebSocket连接可以保持活动状态,服务器可以更好地管理客户端连接,减少服务器开销和处理时间。

WebSocket协议的性能比传统的HTTP请求/响应模型更好,特别是在实时通信和低延迟方面。WebSocket协议适用于需要实时通信和实时数据更新的应用程序,如在线聊天、多人游戏、实时监控等。

2 优化WebSocket的性能

  • 减少消息大小: WebSocket 传输的数据大小对性能有很大影响。尽量减少消息的大小,可以降低网络带宽和服务器负载。例如,可以使用二进制传输协议来代替文本传输,或使用压缩算法对消息进行压缩。
  • 使用CDN加速: 使用 CDN可以将静态资源缓存到离用户更近的节点上,提高传输速度和性能。CDN 可以缓存 Websocket 的初始握手请求,避免不必要的网络延迟。
  • 使用[负载均衡]** WebSocket 服务可以使用负载均衡来分配并平衡多个服务器的负载。负载均衡可以避免单个服务器被过载,并提高整个服务的可伸缩性。
  • 优化服务端代码: WebSocket 服务端代码的性能也是关键因素。使用高效的框架和算法,避免使用过多的内存和 CPU 资源,可以提高服务端的性能和响应速度。
  • 避免网络阻塞: WebSocket 的性能也会受到网络阻塞的影响。当有太多的连接同时请求数据时,服务器的性能会下降。使用合适的线程池和异步 IO 操作可以避免网络阻塞,提高 WebSocket 服务的并发性能。

6. WebSocket的扩展应用和未来发展方向

  • 更加完善的标准规范: WebSocket 标准规范还有很多可以优化的地方,未来可能会继续完善 WebSocket 的标准规范,以适应更加复杂的应用场景。
  • 更加安全的通信方式: 由于 WebSocket 的开放性,使得它可能会受到一些安全威胁,未来可能会通过加密、[身份验证] 等方式来增强 WebSocket 的安全性。
  • 更好的兼容性: WebSocket 协议需要在 HTTP 协议的基础上建立连接,因此可能会遇到兼容性问题,未来可能会通过技术手段来解决这些问题。
  • 更好的性能和可伸缩性: WebSocket 协议的性能和可伸缩性对于复杂的应用场景非常关键,未来可能会通过技术手段来进一步提高 WebSocket 的性能和可伸缩性。

使用

 <global-web-socket  :uri="`/websocket/url1`" @getData="getData" />
// socket传回数据
    getData(data) {
      try {
       console.log(data,'success');
      } catch (err) {
        console.log(err, 'socket');
      }
    },

组件

<template>

</template>
<script>
import store from '@/store';

export default {
  props: {
    uri: {
      type: String
    }
  },

  data() {
    return {
      // webSocket实例
      webSocket: null, 
      // 重连锁,避免多次重连
      lockReconnect: false, 
      // 最大重连次数, -1 标识无限重连
      maxReconnect: 8, 
      // 重连尝试次数
      reconnectTime: 0, 
      heartbeat: {
        // 心跳间隔时间
        interval: 30 * 1000, 
        // 响应超时时间
        timeout: 10 * 1000, 
        // 延时发送心跳的定时器
        pingTimeoutObj: null, 
        // 接收心跳响应的定时器
        pongTimeoutObj: null, 
        // 心跳请求信息
        pingMessage: JSON.stringify({ type: 'ping' }) 
      }
    };
  },

  computed: {},

  created() {
    this.initWebSocket();
  },

  destroyed: function() {
    this.webSocket.close();
    this.clearTimeoutObj(this.heartbeat);
  },

  methods: {
    /**
     * 初始化 weoSocket
     */
    initWebSocket() {
      // ws地址
      const host = window.location.host;
      const wsUri = `ws://${host}${this.uri}?access_token=token`;
      // 建立连接
      this.webSocket = new WebSocket(wsUri);
      // 连接成功
      this.webSocket.onopen = this.onOpen;
      // 连接错误
      this.webSocket.onerror = this.onError;
      // 接收信息
      this.webSocket.onmessage = this.onMessage;
      // 连接关闭
      this.webSocket.onclose = this.onClose;
    },

    /**
     * 重新连接
     */
    reconnect() {
      if (!this.token) {
        return;
      }
      if (this.lockReconnect || (this.maxReconnect !== -1 && this.reconnectTime > this.maxReconnect)) {
        return;
      }
      this.lockReconnect = true;
      setTimeout(() => {
        this.reconnectTime++;
        // 建立新连接
        this.initWebSocket();
        this.lockReconnect = false;
      }, 5000);
    },

    /**
     * 清空定时器
     */
    clearTimeoutObj: function(heartbeat) {
      heartbeat.pingTimeoutObj && clearTimeout(heartbeat.pingTimeoutObj);
      heartbeat.pongTimeoutObj && clearTimeout(heartbeat.pongTimeoutObj);
    },

    /**
     * 开启心跳
     */
    startHeartbeat() {
      const webSocket = this.webSocket;
      const heartbeat = this.heartbeat;
      // 清空定时器
      this.clearTimeoutObj(heartbeat);
      // 延时发送下一次心跳
      heartbeat.pingTimeoutObj = setTimeout(() => {
        // 如果连接正常
        if (webSocket.readyState === 1) {
          // 这里发送一个心跳,后端收到后,返回一个心跳消息,
          webSocket.send(heartbeat.pingMessage);
          // 心跳发送后,如果服务器超时未响应则断开,如果响应了会被重置心跳定时器
          heartbeat.pongTimeoutObj = setTimeout(() => {
            webSocket.close();
          }, heartbeat.timeout);
        } else {
          // 否则重连
          this.reconnect();
        }
      }, heartbeat.interval);
    },

    /**
     * 连接成功事件
     */
    onOpen() {
      console.log('WebSocket connection success');
      // 开启心跳
      this.startHeartbeat();
      this.reconnectTime = 0;
    },

    /**
     * 连接失败事件
     * @param e
     */
    onError(e) {
      // 错误
      console.log(`WebSocket connection error:${e.code} ${e.reason} ${e.wasClean}`);
      // 重连
      this.reconnect();
    },

    /**
     * 连接关闭事件
     * @param e
     */
    onClose(e) {
      // 关闭
      console.log(`WebSocket connection closed:${e.code} ${e.reason} ${e.wasClean}`);
      // 重连
      this.reconnect();
    },

    /**
     * 接收服务器推送的信息
     * @param msgEvent
     */
    onMessage(msgEvent) {
      // 收到服务器信息,心跳重置并发送
      this.startHeartbeat();
      const text = msgEvent.data;
      if (text.indexOf('pong') > 0) {
        return;
      }

      this.$notify.warning({
        title: '消息通知',
        dangerouslyUseHTMLString: true,
        message: text + '消息通知',
        offset: 60
      });
    },

    /**
     * 数据发送
     * @param msg
     */
    send(msg) {
      // 数据发送
      this.webSocket.send(msg);
    }
  }
};

</script>
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,324评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,303评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,192评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,555评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,569评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,566评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,927评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,583评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,827评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,590评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,669评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,365评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,941评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,928评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,159评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,880评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,399评论 2 342

推荐阅读更多精彩内容