在vue中使用SockJS实现webSocket通信
简单介绍基于webSocket通信的库主要有 socket.io,SockJS,这次用的是 SockJS。前提这里我们使用sockjs-client、stomjs这两个模块,要实现webSocket通信,需要后台配合,也使用相应的模块。关于实时通信实现实时通信,我们通常有三种方法:ajax轮询 ajax轮询的原理非常简单,让浏览器每隔几秒就像服务器发送一个请求,询问服务器是...
简单介绍
基于webSocket通信的库主要有 socket.io,SockJS,这次用的是 SockJS。
前提
这里我们使用sockjs-client、stomjs这两个模块,要实现webSocket通信,需要后台配合,也使用相应的模块。
关于实时通信
实现实时通信,我们通常有三种方法:
- ajax轮询 ajax轮询的原理非常简单,让浏览器每隔几秒就像服务器发送一个请求,询问服务器是否有新的信息.
- http 长轮询 长轮询的机制和ajax轮询差不多,都是采用轮询的方式,不过才去的是阻塞模型(一直打电话,没收到就不挂电话),也就是说,客户端发起链接后,如果没有消息,就一直不返回response给客户端.知道有新的消息才返回,返回完之后,客户端再此建立连接,周而复始.
- WebSocket WebSocket是HTML5开始提供的一种在单个TCP连接上进行全双工通讯的协议.在WebSocket API中,浏览器和服务器只需要做一个握手的动作,然后,浏览器和服务器之间就形成了一条快速通道。两者之间就直接可以数据互相传送,不需要繁琐的询问和等待. 从上面的介绍很容易看出来,ajax轮询和长轮询都是非常耗费资源的,ajax轮询需要服务器有很快的处理速度和资源,http长轮询需要有很高的并发,也就是同时接待客户的能力.而WebSocket,只需要经过一次HTTP请求,就可以与服务端进行源源不断的消息收发了.
sockjs-client
sockjs-client是从SockJS中分离出来的用于客户端使用的通信模块.所以我们就直接来看看SockJS. SockJS是一个浏览器的JavaScript库,它提供了一个类似于网络的对象,SockJS提供了一个连贯的,跨浏览器的JavaScriptAPI,它在浏览器和Web服务器之间创建了一个低延迟,全双工,跨域通信通道. 你可能会问,我为什么不直接用原生的WebSocket而要使用SockJS呢?这得益于SockJS的一大特性,一些浏览器中缺少对WebSocket的支持,因此,回退选项是必要的,而Spring框架提供了基于SockJS协议的透明的回退选项。SockJS提供了浏览器兼容性,优先使用原生的WebSocket,如果某个浏览器不支持WebSocket,SockJS会自动降级为轮询.
stomjs
STOMP(Simple Text-Orientated Messaging Protocol) 面向消息的简单文本协议; WebSocket是一个消息架构,不强制使用任何特定的消息协议,它依赖于应用层解释消息的含义. 与HTTP不同,WebSocket是处在TCP上非常薄的一层,会将字节流转化为文本/二进制消息,因此,对于实际应用来说,WebSocket的通信形式层级过低,因此,可以在 WebSocket 之上使用STOMP协议,来为浏览器 和 server间的 通信增加适当的消息语义。
STOMP与WebSocket 的关系:
- HTTP协议解决了web浏览器发起请求以及web服务器响应请求的细节,假设HTTP协议不存在,只能使用TCP套接字来编写web应用,你可能认为这是一件疯狂的事情;
- 直接使用WebSocket(SockJS)就很类似于使用TCP套接字来编写web应用,因为没有高层协议,就需要我们定义应用间发送消息的语义,还需要确保连接的两端都能遵循这些语义;
- 同HTTP在TCP套接字上添加请求-响应模型层一样,STOMP在WebSocket之上提供了一个基于帧的线路格式层,用来定义消息语义.
代码实现
代码中除了最基本的连接,还设置了一个定时器,每隔十秒发送一条数据到服务器端,如果发生错误,catch这个错误,重新建立连接.
这是一个公告通知案例:
// 安装并引入相关模块
import SockJS from 'sockjs-client';
import Stomp from 'stompjs';
export default {
data() {
return {
stompClient:'',
timer:''
};
},
methods: {
initWebSocket() {
this.connection();
let self = this;
// 断开重连机制,尝试发送消息,捕获异常发生时重连
this.timer = setInterval(() => {
try {
self.stompClient.send("test");
} catch (err) {
console.log("断线了: " + err);
self.connection();
}
}, 10000);
},
connect() {
//连接服务端提供的通信接口,连接以后才可以订阅广播消息和个人消息
var sock = new SockJS('http://127.0.0.1::8080/websocket/endpoint')
// 获取STOMP子协议的客户端对象
this.stompClient = Stomp.over(sock)
var token = sessionStorage.getItem('cookieaccess_token')
// 向服务器发起websocket连接
var connection = this.stompClient.connect({ Authorization: "Bearer " + token }, (message) => {
this.subscribe();
this.sendMessage();
});
},
sendMessage() { // 发送消息
this.stompClient.send("/welcome", {}, JSON.stringify({ 'name': 'Marvin' }));
},
subscribe() { // 订阅公告
this.stompClient.subscribe('/user/notice', function (greeting) {
var obj = JSON.parse(greeting.body)
obj.id = id_string;
var _type = ''
var _title = ''
if (greeting.headers.msg_type == 'announce') {
_type = '公告'
_title = obj.title
} else if (greeting.headers.msg_type == 'notice') {
if (obj.deploymentKey == 'customerReName') { // 客户更名申请
_type = '通知'
_title = obj.title
} else if (obj.deploymentKey == 'customerChangeBelong') { // 客户转归属申请
_type = '通知'
_title = obj.title
}
}
this.clear1=setTimeout(() => {
alert('【' + _type + '】' + _title);
}, 3000)
});
},
// 断开连接
disconnect() {
if (this.stompClient != null) {
this.stompClient.disconnect();
console.log("Disconnected");
}
}
},
mounted:function(){
this.initWebSocket();
},
beforeDestroy: function () {
// 页面离开时断开连接,清除定时器
this.disconnect();
clearInterval(this.timer);
},
};
更多推荐
所有评论(0)