Websocket
什么是websocket?
WebSocket 是一种独立的、创建在 TCP 上的网络通讯协议。
WebSocket需要像TCP一样,先建立连接,连接成功后才能相互通信。
通过websocket,可以实现客户端与服务器之间的双向的平等的通讯。
为什么需要websocket?
在普通的场景中,客户端和服务端之间的通讯是由客户端主动发起的,服务器收到了客户端的请求后,返回对应的数据。
在一些特殊场景中,需要服务器主动发送数据到客户端,客户端被动接收。
例如: 获取扫描进度时,没有websocket之前,我们会才用定时刷新的方式,或者时前端做假进度的方式来实现。前者多余的请求相应会带来更多的资源消耗;后者可能会导致信息传递不及时。
html5 新加入websocket以后就解决了这些问题,服务器端和客户端可以进行双向的平等的数据通讯,并且只用建里一次连接,就可以进行多次通信。二者均可以主动向对方发送信息。
和http长连接的区别:
http长连接的本质还是由客户端主动发起的,不能由服务器端发起
用来解决服务器主动向客户端发送信息的问题。是真正的双向平等对话。
使用场景: 需要实时更新或监控的信息,例如任务进度。强调获取数据的实时性。
如何使用:
一个简单的例子
具体使用参考 developer.mozilla.org/zh-CN/docs/…
// websocket 的使用流程
// 1.创建实例
// 2.开始连接
// 3.消息传输(客户端发送消息,或者对收到的消息进行处理)
// 4.关闭连接
var ws;
connection () {
// 创建一个websocket实例
ws = new WebSocket('wss://192.168.170.201:8333/endpointWisely/836/kkigweo1/websocket')
ws.onopen = function (evt) { // 建立连接
console.log('Connection open ...')
ws.send('Hello WebSockets!')
}
ws.onmessage = function (evt) { // 收到消息
console.log('Received Message: ' + evt.data)
ws.close()
}
ws.send('message') // 发送消息
ws.onclose = function (evt) { // 连接关闭
console.log('Connection closed.')
}
ws.onerror = function(event) {
// handle error event
};
},
disconnect () {
ws.close() // 主动关闭连接
}
SOCKJS
什么是SockJS?
SockJS是一个JavaScript库。用来解决websocket支持性不够的问题
SockJS 是 WebSocket 技术的一种模拟,或者说是websocket的备选方案。
为什么需要SockJS?
websocket作为html5新增的特性,对主流浏览器支持性好,但是IE及很多低版本的浏览器仍无法使用。因此使用前,需要先判断浏览器是否支持websocket,如果不支持的话仍需采用传统方法解决问题。
if ("WebSocket" in window) {
// 支持,可以继续使用websocket
} else {
// 不支持websocket。改用其他方式,如 轮询
}
这样就显得繁琐了,websocket用起来也不是那么方便了。如果可以封装起来,先使用websocket连接,不行的话再自动改为轮询就好了。
而正好sockJS就时为了解决这样的问题。就像上面说的一样,sockJS就是为了解决websocket的支持性不好的。
原理:
SockJS会优先选择WebSocket进行连接,但是当服务器或客户端不支持WebSocket时,会自动在 XHR流、XDR流、iFrame事件源、iFrame HTML文件、XHR轮询、XDR轮询、iFrame XHR轮询、JSONP轮询 这几个方案中择优进行连接。
如何使用?
sockJS其实是webscoket其实就是备选方案,所以除了初始化实例不同以外,其他的跟websocket的类似。
具体使用参考 www.npmjs.com/package/soc…
var sockjs = new SockJS ( url , _reserved , options ) ;
// 这里接收的url 是http或者https的
// _reserved 文档里没写,源码里用的是protocols,重要功能里没有用到这个参数。可以直接设置为 null 或者 []
// 这里注意option的配置
options = {
// 实际连接的url = `url/${server}/${sessionId}`
server: '3312', // 可以指定加在url后面的字符串,例如 wss://192.168.170.201:8333/endpointWisely/3312
transports:'', // 设置传输方式,默认所有可用的方式。在确定有些方式可以不使用的时候可以去掉,减少连接时间。
sessionId: '', // 会话标识。用来区分不同的连接。当sessionId为number,则指的是sessionId随机的长度。如果想要自定义sessionId的话,需要写一个函数,通过函数返回。
timeout: 2000, // 这个是设置传输连接的超时时间的。通常如果连接时间长的时候设定
}
sockjs.onopen = (evt) => {
console.log('Connection open ...', evt)
sockjs.send('Hello WebSockets!')
}
sockjs.onmessage = function(msg)
console.log('接收到的数据', msg)
}
sockjs.onclose = function (evt) {
console.log('Connection closed.')
}
stompJS
什么是 stompJS?
Simple Text Oriented Message Protocol——面向消息的简单文本协议
STOMP协议,来为浏览器 和 服务器间的 通信增加适当的消息语义。
可以通过它在底层协议上加一层协议,使双方遵循这种协议来发送消息。
为什么要用stompJS?
1、WebSocket中所有发送的数据使用帧的形式发送,跟tcp没什么差别,是不需要Request消息的。而我们要定义应用间所发送消息的语义,还需要确保连接的两端都能遵循这些语义。
2、同HTTP在TCP 套接字上添加请求-响应模型层一样,STOMP在WebSocket 之上提供了一个基于帧的线路格式层,用来定义消息语义;
如何使用?
详细使用参考 jmesnil.net/stomp-webso…
- 创建stomp客户端
- 可以对客户端进行一些配置(比如心跳配置)
- 开始连接
- 连接成功后进行订阅传输消息的通道
- 进行数据传输(收到订阅的消息,或者发送消息)
- 关闭连接
创建
// 在浏览器中两种创建方式
// 1. 使用原生websocket来创建。
var url = "ws://localhost:61614/stomp";
var client = Stomp.client(url);
// 2. 使用其他类型的websocket创建
var ws = new SockJS(url);
var client = Stomp.over(ws);
心跳:发送和接收频率。如果没有消息传递,websocket在一段时间内未进行通信的话会自动断开连接(通常90s)。所以需要定时通信防止连接断开。使用原生websocket需要自己手动实现心跳功能。
心跳设置
// heartbeat配置心跳,默认开启,值均为 1000,单位为ms
client.heartbeat.outgoing = 20000; // 发送频率为20000ms一次
client.heartbeat.incoming= 0; // 接收频率,0表示不想接受服务器端的心跳
连接到服务器,进行消息订阅
// 连接时可以通过headers传递一些表单信息
let headers = {};
client.connect(headers, (frame) => {
// 连接成功进行消息订阅,要在浏览器中接收消息,STOMP 客户端必须首先订阅目的地。
// 同样可以设置headers,比如设置消息订阅id
let msgHeader = { id: 'myId' };
var subsiption = client.subscribe("/queue/test", (msg) => {
// 服务器每次发送消息时都会触发这个回调函数
// 通过msg.body 可以拿到目的地发送的数据。发送和接收的消息内容都只能是字符串
}, msgHeader );
// 发送信息
let sendHeader = {priority: 9}
client.send("/queue/test", sendHeader, "someMessage");
// 还可以通过unsubscribe停止接收消息
// ...
subscription.unsubscribe();
})
消息通道的订阅
发送消息
接收消息
断开连接
// 可以直接disconnect()断开连接
client.disconnect(function() {
alert("See you next time!");
};