- SockJS的url是http、https协议,而不是 ws
- 提供Websocket兼容性实现方法
- new WebSocket(url) url必须是以
ws://
或者wss://
开始的一个完全限定URL。
const socket = new SockJS("http://127.0.0.1:9091/sbjm-cheng/endpointOyzc");
Stomp.over(socket)
const ws = new Websocket("ws://localhost:61614/ws")
Stomp.over(ws)
摘自: 前端vue使用stomp.js、sock.js完成websocket - shine_lovely - 博客园 (cnblogs.com)
- stompjs
- 提供类似http这种通讯协议,增加语义
- STOMP Over WebSocket (jmesnil.net) 官网
- 前后端websocket都用stomp才有意义
-
WebSocket协议定义了两种URL方案(URL Scheme):
- ws(WebSocket):客户端与服务器之间的非加密流量,与HTTP URI方案类似
- wss(WebSocket Secure):客户端与服务器之间的加密流量,该方案表示使用传输层安全性(TLS,也叫SSL)的WebSocket连接,使用HTTPS采用的安全机制来保证HTTP连接安全
-
除了文本,WebSocket消息还可以处理二进制数据,这种数据作为Blob消息或ArrayBuffer消息。
-
WebSocket 发送文本/二进制消息
ws.close(1000, "Closing normally");
close()方法传递两个可选参数: code(数字型的状态代码)和reason()一个文本字符串。
向服务器传递关于关闭连接的原因。
websocket知识
- 下面是从stompjs官网摘录翻译的关键部分
初始化创建stomp实例
使用普通的websockt
var client= Stomp.client("ws://localhost:61614/stomp");
Stomp.client(url, protocols) //protocols可以是字符串或数组
默认protocols是['v10.stomp', 'v11.stomp']
使用自定义的websocket
- stompjs默认使用浏览器的
WebSocket
类来生成websocket - 考虑到浏览器不支持/浏览器websocket类名不叫WebSocket
- 使用
Stomp.over(ws)
处理这种情况
var ws = new SockJS(url);//sockjs不支持ws://这种url
var client = Stomp.over(ws);
//注意 使用Stomp.over时,里面传的是遵守WebSocket定义的对象
建立连接
- 前面STOMP client创建好后,需要使用实例的connect方法
------ 方式1
client.connect(login, passcode, connectCallback);
client.connect(login, passcode, connectCallback, errorCallback);
client.connect(login, passcode, connectCallback, errorCallback, host);
//前俩参数是string,后俩参数是object
------- 方式2
client.connect(headers, connectCallback);
client.connect(headers, connectCallback, errorCallback);
//一旦使用这种形式 就必须要有login和passcode(未验证,文档上这么写的)
var headers = {
login: 'mylogin',
passcode: 'mypasscode',
// additional header(比如token之类的,往后写)
'client-id': 'my-client-id'
};
client.connect(headers, connectCallback)
断开连接
client.disconnect(function() {
alert("See you next time!");
};
心跳
- 默认心跳10s
client.heartbeat.outgoing = 20000; // client will send heartbeats every 20000ms
client.heartbeat.incoming = 0; // client does not want to receive heartbeats from the server
//依靠setInterval来保持心跳
发消息
// 目标地址,请求头(可以是空对象),请求体(string,想发对象可以用json字符串)
client.send("/queue/test", {priority: 9}, "Hello, STOMP");
收消息
- STOMP client订阅地址后才能收消息
//client.subscribe会返回一个对象(带id属性以及unsubscribe()方法),
var subscription = client.subscribe("/queue/test", callback);
- 第三个参数可以给订阅地址实例加自定义id,也可以自定义请求头
- headers看着更像是限定,不合规定的数据不收(没太看懂)
封装websocket
- 参考网上一些文章融合的
// websocket.js
/**
* 使用方法
* var ws=new Socket(url,事件接收回调函数)
* ws.close()
* 由于重连后socket的值是new一个新的WebSocket对象,所以new Socket得到的实例里的Socket属性和重连后的Socket不是一个东西,
*
*/
export class Socket {
Socket = "";
setIntervalWesocketPush = null;
URL = "";
reconnectTime = 0;
limitTime = 10;
onmessageWS;
constructor(url, onmessageWS) {
this.URL = url;
this.onmessageWS = (val) => {
if (val.data === "pong") {
console.log(val.data);
}
onmessageWS(val);
};
this.createSocket();
}
/**建立websocket连接 */
createSocket() {
// Socket && Socket.close()
if (!this.Socket) {
console.log("建立websocket连接");
this.Socket = new WebSocket(this.URL);
this.Socket.onopen = this.onopenWS;
this.Socket.onmessage = this.onmessageWS;
this.Socket.onerror = this.onerrorWS;
this.Socket.onclose = this.oncloseWS;
} else {
console.log("websocket已连接");
}
}
/**打开WS之后发送心跳 */
onopenWS = () => {
this.reconnectTime = 0;
this.sendPing();
};
/**连接失败重连 */
onerrorWS = () => {
this.Socket.close();
clearInterval(this.setIntervalWesocketPush);
console.log("连接失败重连中");
if (this.Socket.readyState !== 3) {
this.reconnectTime++;
this.Socket = null;
if (this.reconnectTime < this.limitTime) {
this.createSocket(URL);
} else {
console.log("超出尝试次数");
}
}
};
/**
* 发送数据但连接未建立时进行处理等待重发
* @param {any} message 需要发送的数据
*/
connecting = (message) => {
setTimeout(() => {
if (this.Socket.readyState === 0) {
this.connecting(message);
} else {
this.Socket.send(JSON.stringify(message));
}
}, 1000);
};
/**
* 发送数据
* @param {any} message 需要发送的数据
* readyState
* 0 - 表示连接尚未建立。
* 1 - 表示连接已建立,可以进行通信。
* 2 - 表示连接正在进行关闭。
* 3 - 表示连接已经关闭或者连接不能打开。
*/
sendWSPush = (message) => {
if (this.Socket !== null && this.Socket.readyState === 3) {
this.Socket.close();
this.createSocket();
} else if (this.Socket.readyState === 1) {
this.Socket.send(JSON.stringify(message));
} else if (this.Socket.readyState === 0) {
this.connecting(message);
}
};
/**断开重连 */
oncloseWS = () => {
clearInterval(this.setIntervalWesocketPush);
console.log("websocket已断开....正在尝试重连");
if (this.Socket.readyState !== 2) {
this.reconnectTime++;
this.Socket = null;
if (this.reconnectTime < this.limitTime) {
this.createSocket(URL);
} else {
console.log("超出尝试次数");
}
}
};
/**发送心跳
* @param {number} time 心跳间隔毫秒 默认25s
* @param {string} ping 心跳名称 默认字符串ping
*/
sendPing = (time = 25000, ping = "ping") => {
clearInterval(this.setIntervalWesocketPush);
this.Socket.send(ping);
this.setIntervalWesocketPush = setInterval(() => {
this.Socket.send(ping);
}, time);
};
/**关闭socket */
close() {
this.Socket.close();
}
}