webSocket实时通信

Websocket real-time communication

Posted by ZeFeng on October 14, 2018

实时通信

实时通信的实现方式有很多种,比如:短轮询、长轮询、长连接,本质都是单向通信,客户端主动发起请求,服务端被动响应请求。而WebSocket则是全双工通讯了,也就是说无论是客户端还是服务端都能主动向对方发起响应,这样服务器具备推送能力。

前言

SockJS实现webSocket通信有很多例子,比如用jq实现的,也有用vue实现的。这里我们主要讲vue的例子。我们先用一个图简单了解一下轮询跟WebSocket。

简介

WebSocket: WebSocket 是 HTML5 开始提供的一种在单个 TCP 连接上进行全双工通讯的协议。
WebSocket 使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据。
在 WebSocket API 中,浏览器和服务器只需要完成一次握手,两者之间就直接可以创建持久性的连接,并进行双向数据传输。
SockJS:
SockJS是一个浏览器JavaScript库,它提供了一个类似于网络的对象。SockJS提供了一个连贯的、跨浏览器的Javascript API,它在浏览器和web服务器之间创建了一个低延迟、全双工、跨域通信通道。

使用SockJS的原因

一些浏览器中缺少对WebSocket的支持,因此,回退选项是必要的,而Spring框架提供了基于SockJS协议的透明的回退选项。
SockJS的一大好处在于提供了浏览器兼容性。优先使用原生WebSocket,如果在不支持websocket的浏览器中,会自动降为轮询的方式。
除此之外,spring也对socketJS提供了支持。
如果代码中添加了withSockJS()如下,服务器也会自动降级为轮询。

registry.addEndpoint("/coordination").withSockJS();

代码实现

服务端:
可以到github看代码 SockJS-node-server
客户端:
1、安装stompjs

npm install stompjs
npm install --save net

2、安装sockjs

npm install sockjs

3、代码实现

// 引入模块
import SockJS from  'sockjs-client'
import  Stomp from 'stompjs'
export default {
    data() {
      return {
        dataList: []
      };
    },
    mounted:function(){
      this.initWebSocket()
    },
    beforeDestroy: function () {
      // 页面离开时断开连接
      this.disconnect()
     // 清除定时器
      clearInterval(this.timer)
    },
    methods: {
      initWebSocket() {
        this.connection()
        let self = this // 作用域,this的指向
        // 断开重连机制,尝试发送消息,捕获异常发生时重连
        this.timer = setInterval(() => {
          try {
            self.stompClient.send('test')
          } catch (err) {
            console.log('断线了: ' + err)
            self.connection()
          }
        }, 5000);
      },
      connection() {
      // 建立连接对象,连接服务端提供的通信接口,连接以后才可以订阅广播消息和个人消息
        this.socket = new SockJS('你的服务请求地址,例如:https://mydomain.com/my_prefix')
        // 获取STOMP子协议的客户端对象
        this.stompClient = Stomp.over(this.socket)
        // 定义客户端的认证信息,按需求配置
        var headers = {
          'login': , // 按需求配置
          'passcode': , // 按需求配置
          'client-id': util.uuid() // 可以理解为一个需要认证的参数
          // additional header
        };
        // 向服务器发起websocket连接
        this.stompClient.connect(headers,(frame) => {
       // 服务端提供的某个topic,按服务端提供的进行修改
          this.stompClient.subscribe('/topic/chat_demo', (res) => { 
           consolel.log(res.data.info)  // res.data.info存放的是服务端发送给我们的信息
          });
        }, (err) => {
            // 连接发生错误时的处理函数
            console.log(err)
        });

      },
      // 断开连接
      disconnect() {
        if (this.stompClient !== null) {
          this.stompClient.disconnect()
          console.log('Disconnected')
        }
      }
    }
}

结语

这只是一个简单的例子,需要深入学习的同学可以看下: sockjs-client