socket.io 在 x seconds/first 尝试获得响应失败后停止重新发送事件
socket.io stop re-emitting event after x seconds/first failed attempt to get a response
我注意到每当我的服务器离线时,当我将其切换回在线时,它会收到大量套接字事件,这些事件是在服务器关闭时触发的。 (现在已经过时的事件)。
有没有办法阻止 socket.io 在 x 秒内未收到响应后重新发出事件?
当开源库的所有其他方法都失败时,你去研究代码,看看你能找出什么。在花了一些时间使用 socket.io 源代码之后...
问题的症结似乎是 socket.emit()
中的 here 代码:
if (this.connected) {
this.packet(packet);
} else {
this.sendBuffer.push(packet);
}
如果套接字未连接,所有通过 .emit()
发送的数据都缓冲在 sendBuffer
中。然后,当套接字再次连接时,我们看到:
Socket.prototype.onconnect = function(){
this.connected = true;
this.disconnected = false;
this.emit('connect');
this.emitBuffered();
};
Socket.prototype.emitBuffered = function(){
var i;
for (i = 0; i < this.receiveBuffer.length; i++) {
emit.apply(this, this.receiveBuffer[i]);
}
this.receiveBuffer = [];
for (i = 0; i < this.sendBuffer.length; i++) {
this.packet(this.sendBuffer[i]);
}
this.sendBuffer = [];
};
所以,这充分解释了为什么它在连接断开时缓冲所有发送的数据,然后在重新连接时发送所有数据。
现在,关于如何防止它发送此缓冲数据,这是一个理论,我将在今晚晚些时候有更多时间时尝试测试。
有两件事看起来像是一个机会。套接字在发送缓冲数据之前通知 connect
事件,并且 sendBuffer
是套接字的 public 属性。因此,看起来您可以在客户端代码中执行此操作(连接时清除缓冲区):
// clear previously buffered data when reconnecting
socket.on('connect', function() {
socket.sendBuffer = [];
});
我刚刚测试了它,它工作得很好。我有一个客户端套接字,它每秒向服务器发送一个递增的计数器消息。我将服务器关闭 5 秒钟,然后当我在添加此代码之前将服务器重新启动时,所有排队的消息都会到达服务器。没有遗漏任何计数。
当我添加上面的三行代码时,服务器关闭时发送的任何消息都不会发送到服务器(从技术上讲,它们会在发送前从发送缓冲区中清除)。有效。
仅供参考,另一种可能性是在未连接套接字时不调用 .emit()
。因此,您可以只创建自己的函数或方法,它只会在套接字实际连接时尝试 .emit()
,因此任何东西都不会进入 sendBuffer
.
Socket.prototype.emitWhenConnected = function(msg, data) {
if (this.connected) {
return this.emit(msg, data);
} else {
// do nothing?
return this;
}
}
或者,更危险的是,您可以覆盖 .emit()
以使其以这种方式工作(不是我的建议)。
我注意到每当我的服务器离线时,当我将其切换回在线时,它会收到大量套接字事件,这些事件是在服务器关闭时触发的。 (现在已经过时的事件)。
有没有办法阻止 socket.io 在 x 秒内未收到响应后重新发出事件?
当开源库的所有其他方法都失败时,你去研究代码,看看你能找出什么。在花了一些时间使用 socket.io 源代码之后...
问题的症结似乎是 socket.emit()
中的 here 代码:
if (this.connected) {
this.packet(packet);
} else {
this.sendBuffer.push(packet);
}
如果套接字未连接,所有通过 .emit()
发送的数据都缓冲在 sendBuffer
中。然后,当套接字再次连接时,我们看到:
Socket.prototype.onconnect = function(){
this.connected = true;
this.disconnected = false;
this.emit('connect');
this.emitBuffered();
};
Socket.prototype.emitBuffered = function(){
var i;
for (i = 0; i < this.receiveBuffer.length; i++) {
emit.apply(this, this.receiveBuffer[i]);
}
this.receiveBuffer = [];
for (i = 0; i < this.sendBuffer.length; i++) {
this.packet(this.sendBuffer[i]);
}
this.sendBuffer = [];
};
所以,这充分解释了为什么它在连接断开时缓冲所有发送的数据,然后在重新连接时发送所有数据。
现在,关于如何防止它发送此缓冲数据,这是一个理论,我将在今晚晚些时候有更多时间时尝试测试。
有两件事看起来像是一个机会。套接字在发送缓冲数据之前通知 connect
事件,并且 sendBuffer
是套接字的 public 属性。因此,看起来您可以在客户端代码中执行此操作(连接时清除缓冲区):
// clear previously buffered data when reconnecting
socket.on('connect', function() {
socket.sendBuffer = [];
});
我刚刚测试了它,它工作得很好。我有一个客户端套接字,它每秒向服务器发送一个递增的计数器消息。我将服务器关闭 5 秒钟,然后当我在添加此代码之前将服务器重新启动时,所有排队的消息都会到达服务器。没有遗漏任何计数。
当我添加上面的三行代码时,服务器关闭时发送的任何消息都不会发送到服务器(从技术上讲,它们会在发送前从发送缓冲区中清除)。有效。
仅供参考,另一种可能性是在未连接套接字时不调用 .emit()
。因此,您可以只创建自己的函数或方法,它只会在套接字实际连接时尝试 .emit()
,因此任何东西都不会进入 sendBuffer
.
Socket.prototype.emitWhenConnected = function(msg, data) {
if (this.connected) {
return this.emit(msg, data);
} else {
// do nothing?
return this;
}
}
或者,更危险的是,您可以覆盖 .emit()
以使其以这种方式工作(不是我的建议)。