我正在使用将PHP5和Chrome浏览器用作客户端的Web套接字。我已从http://code.google.com/p/phpwebsocket/网站获取了代码。
我运行服务器,并且客户端也已连接。我也可以聊天。现在,当我重新启动服务器(通过杀死它并重新启动它)时,客户端会获得断开连接的信息,但是当我发送消息时,客户端不会自动与服务器重新连接。
如何实现呢?就像我收到断开连接的信息一样,是否应该检查它并将其发送给JavaScript以刷新页面或重新连接?
我正在使用将PHP5和Chrome浏览器用作客户端的Web套接字。我已从http://code.google.com/p/phpwebsocket/网站获取了代码。
我运行服务器,并且客户端也已连接。我也可以聊天。现在,当我重新启动服务器(通过杀死它并重新启动它)时,客户端会获得断开连接的信息,但是当我发送消息时,客户端不会自动与服务器重新连接。
如何实现呢?就像我收到断开连接的信息一样,是否应该检查它并将其发送给JavaScript以刷新页面或重新连接?
Answers:
服务器重新启动时,Web套接字连接将关闭,因此将onclose
触发JavaScript 事件。这是一个示例,尝试每五秒钟重新连接一次。
function start(websocketServerLocation){
ws = new WebSocket(websocketServerLocation);
ws.onmessage = function(evt) { alert('message received'); };
ws.onclose = function(){
// Try to reconnect in 5 seconds
setTimeout(function(){start(websocketServerLocation)}, 5000);
};
}
start
递归调用而从未返回。
Andrew提供的解决方案无法完美运行,因为如果失去连接,服务器可能会发送多个关闭事件。
在这种情况下,您将设置几个setTimout。仅当服务器在五秒钟前准备就绪时,安德鲁给出的解决方案才可能起作用。
然后,根据安德鲁解决方案进行了重新设计,我使用了setInterval将ID附加到窗口对象(这样,“随处可见”):
var timerID=0;
var socket;
/* Initiate what has to be done */
socket.onopen=function(event){
/* As what was before */
if(window.timerID){ /* a setInterval has been fired */
window.clearInterval(window.timerID);
window.timerID=0;
}
/* ... */
}
socket.onclose=function(event){
/* ... */
if(!window.timerID){ /* Avoid firing a new setInterval, after one has been done */
window.timerID=setInterval(function(){start(websocketServerLocation)}, 5000);
}
/* That way, setInterval will be fired only once after losing connection */
/* ... */
}
setTimeout
如果您将“全局计时器ID”概念应用到它们,则仍然可以使用;)
onclose
事件将再次被触发。
GitHub上有一个小的JavaScript库,该库装饰WebSocket API以提供WebSocket连接,如果断开连接,该连接将自动重新连接。
使用gzip压缩的压缩库小于600个字节。
官方存储库位于此处:
https://github.com/joewalnes/reconnecting-websocket
重新启动时,如果有大量客户端连接到服务器。通过使用指数退避算法来管理客户端的重新连接时序可能是值得的。
该算法的工作原理如下:
参考:
http://blog.johnryding.com/post/78544969349/how-to-reconnect-web-sockets-in-a-realtime-web-app
ReconnectingWebSocket不使用此算法处理重新连接。
我已经将这种模式用于纯香草JavaScript已有一段时间了,它比其他答案支持更多案例。
document.addEventListener("DOMContentLoaded", function() {
'use strict';
var ws = null;
function start(){
ws = new WebSocket("ws://localhost/");
ws.onopen = function(){
console.log('connected!');
};
ws.onmessage = function(e){
console.log(e.data);
};
ws.onclose = function(){
console.log('closed!');
//reconnect now
check();
};
}
function check(){
if(!ws || ws.readyState == 3) start();
}
start();
setInterval(check, 5000);
});
服务器关闭连接后,此操作将重试,并且将检查连接以确保每5秒也启动一次。
因此,如果服务器在运行时或在onclose事件发生时未启动,则一旦连接恢复在线,连接仍将恢复。
注意:使用此脚本不会让您永远停止尝试打开连接...但是我想这就是您想要的?
以下是我在我的项目中使用的代码,它们可以100%工作。
var name = sessionStorage.getItem('name');
wsUri = "ws://localhost:8080";
var websocket;
$(function() {
init();
$("#chat_text_box").on("keypress", function(e) {
if (e.keyCode == 13) { //For Enter Button
e.preventDefault();
var mymessage = $('#chat_text_box').val();
if(mymessage){
var msg = { type: 'chat_text', data : { name:name, msg:mymessage } };
console.log(msg);
websocket.send(JSON.stringify(msg));
$('#chat_text_box').val('');
}
return false;
}
});
});
function init() {
websocket = new WebSocket(wsUri);
websocket.onopen = function(ev) { /*connection is open */ }
websocket.onmessage = function(ev) {
var data = JSON.parse(ev.data); //PHP sends Json data
var type = data.type;//alert(JSON.stringify(data));
switch(type) {
case "chat_text":
var text = "<div><span class='user'>"+data.data.sender_name+" : </span><span class='msg'>"+data.data.msg+"</span></div>";
$('#chat-messages').append(text);
break;
default:
break;
}
};
websocket.onerror = function(ev){};
websocket.onclose = function(ev) { init(); };
}
无法发表评论,但以下内容:
var socket;
const socketMessageListener = (event) => {
console.log(event.data);
};
const socketOpenListener = (event) => {
console.log('Connected');
socket.send('hello');
};
const socketCloseListener = (event) => {
if (socket) {
console.error('Disconnected.');
}
socket = new WebSocket('ws://localhost:8080');
socket.addEventListener('open', socketOpenListener);
socket.addEventListener('message', socketMessageListener);
socket.addEventListener('close', socketCloseListener);
};
socketCloseListener();
// for testing
setTimeout(()=>{
socket.close();
},5000);
加上https://www.npmjs.com/package/back已经足够好了:)
function wsConnection(url){
var ws = new WebSocket(url);
var s = (l)=>console.log(l);
ws.onopen = m=>s(" CONNECTED")
ws.onmessage = m=>s(" RECEIVED: "+JSON.parse(m.data))
ws.onerror = e=>s(" ERROR")
ws.onclose = e=>{
s(" CONNECTION CLOSED");
setTimeout((function() {
var ws2 = new WebSocket(ws.url);
ws2.onopen=ws.onopen;
ws2.onmessage = ws.onmessage;
ws2.onclose = ws.onclose;
ws2.onerror = ws.onerror;
ws = ws2
}
).bind(this), 5000)
}
var f = m=>ws.send(JSON.stringify(m)) || "Sent: "+m;
f.ping = ()=>ws.send(JSON.stringify("ping"));
f.close = ()=>ws.close();
return f
}
c=new wsConnection('wss://echo.websocket.org');
setTimeout(()=>c("Hello world...orld...orld..orld...d"),5000);
setTimeout(()=>c.close(),10000);
setTimeout(()=>c("I am still alive!"),20000);
<pre>
This code will create a websocket which will
reconnect automatically after 5 seconds from disconnection.
An automatic disconnection is simulated after 10 seconds.
最后,我在vue + ts中使ws自动重新连接,如下所示:
private async mounted() {
// Connect to WebSocket
const sn = "sb1234567890";
const host =
window.location.protocol == "https:"
? "wss://www.xxx.net"
: process.env.DEV_TYPE === "fullstack"
? "ws://10.0.0.14:8528"
: "ws://www.xxx.net:8528";
const wsUri = host + "/feed-home/" + sn;
await this.startWs(wsUri, sn);
// !!!Deprecated: failed to reconnect
// let ws = new WebSocket();
// console.log(ws);
// ws.onopen = async function(event) {
// console.log(event, "openEvent");
// clearInterval(that.timer);
// };
// ws.onclose = async function(event) {
// console.log(event, "close");
// that.timer = setInterval(() => {
// console.log("Heart Beat");
// ws.send("HeartBeat");
// // ws = new WebSocket("ws://10.0.0.14:8528/feed-home/" + sn);
// console.log(ws);
// }, 60000);
// };
// ws.onmessage = async function(event) {
// console.log(event, "ws");
// alert("get it!");
// await alert("please update!");
// await that.getHome(sn);
// };
}
private wsReconnected: boolean = false; // check whether WebSocket is reconnected
private async startWs(uri: string, sn: string) {
let that = this;
let ws = new WebSocket(uri);
ws.onopen = async () => {
if (that.wsReconnected) {
await that.getHome(sn); // Refresh api data after reconnected
}
ws.send("Current client version: " + window.version);
};
ws.onmessage = async evt => {
await that.getHome(sn);
that.$message({
type: "success",
message: evt.data,
showClose: true,
center: true,
duration: 20 * 1000
});
};
ws.onclose = async () => {
that.wsReconnected = true;
await that.startWs(uri, sn);
const sleep = (seconds: number) => {
return new Promise(resolve =>
setTimeout(resolve, seconds * 1000)
);
};
await sleep(10); // Try to reconnect in 10 seconds
// !!!Deprecated: Use timer will cause multiply ws connections
// if (!that.wsTimer) {
// // Try to reconnect in 10 seconds
// that.wsTimer = setInterval(async () => {
// console.log("reconnecting websocket...");
// await that.startWs(uri, sn);
// }, 10 * 1000);
// }
};
}
WebSocket的客户端关闭事件具有wasClean属性,这对我很有用。似乎在客户端计算机进入睡眠模式等情况下或在服务器意外停止等情况下将其设置为true。如果手动关闭套接字,则将其设置为false,在这种情况下,您不想打开套接字自动再次。下面的代码来自Angular 7项目。我在服务中有此代码,因此可以从任何组件中使用。
notifySocketClose(event) {
if (!event.wasClean) {
setTimeout(() => {
this.setupSocket()
}, 1000);
}
}
setupSocket() { // my function to handle opening of socket, event binding etc.
.....
.....
this.websocketConnection = this.websocketConnection ? this.websocketConnection : new WebSocket(socketUrl);
this.websocketConnection.onclose = this.notifySocketClose.bind(this);
}
}
.....
.....