socket.io在x秒/第一次失败尝试获得响应后停止重新发出事件

时间:2022-08-22 16:32:01

I noticed that whenever my server is offline, and i switch it back online, it receives a ton of socket events, that have been fired while server was down. ( events that are ... by now outdated ).

我注意到,只要我的服务器处于脱机状态,并且我将其重新联机,它就会收到大量的套接字事件,这些事件在服务器关闭时被触发。 (现在已经过时的事件)。

Is there a way to stop socket.io from re-emitting the events after they have not received a response for x seconds ?.

有没有办法阻止socket.io在没有收到x秒的响应后重新发出事件?

1 个解决方案

#1


15  

When all else fails with open source libraries, you go study the code and see what you can figure out. After spending some time doing that with the socket.io source code...

当所有其他方法都失败了开源库时,你会去研究代码,看看你能弄清楚什么。花了一些时间用socket.io源代码做了...

The crux of the issue seems to be this code that is here in socket.emit():

这个问题的关键似乎是socket.emit()中的代码:

  if (this.connected) {
    this.packet(packet);
  } else {
    this.sendBuffer.push(packet);
  }

If the socket is not connected, all data sent via .emit() is buffered in the sendBuffer. Then, when the socket connects again, we see this:

如果未连接套接字,则通过.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 = [];
};

So, this fully explains why it buffers all data sent while the connection is down and then sends it all upon reconnect.

因此,这完全解释了为什么它在连接断开时缓冲所有发送的数据,然后在重新连接时发送所有数据。

Now, as to how to prevent it from sending this buffered data, here's a theory that I will try to test later tonight when I have more time.

现在,至于如何防止它发送这个缓冲数据,这是一个理论,我将在今晚晚些时候尝试测试我有更多时间。

Two things look like they present an opportunity. The socket notifies of the connect event before it sends the buffered data and the sendBuffer is a public property of the socket. So, it looks like you can just do this in the client code (clear the buffer upon connect):

两件事看起来像是一个机会。套接字在发送缓冲数据之前通知connect事件,sendBuffer是套接字的公共属性。所以,看起来你可以在客户端代码中执行此操作(在连接时清除缓冲区):

// clear previously buffered data when reconnecting
socket.on('connect', function() {
    socket.sendBuffer = [];
});

I just tested it, and it works just fine. I have a client socket that sends an increasing counter message to the server every second. I take the server down for 5 seconds, then when I bring the server back up before adding this code, all the queued up messages arrive on the server. No counts are missed.

我刚试过它,它运行得很好。我有一个客户端套接字,每秒向服务器发送一个增加的计数器消息。我将服务器关闭了5秒钟,然后当我在添加此代码之前重新启动服务器时,所有排队的消息都会到达服务器上。没有错过任何计数。

When, I then add the three lines of code above, any messages sent while the server is down are not sent to the server (technically, they are cleared from the send buffer before being sent). It works.

然后,当我添加上面三行代码时,服务器关闭时发送的任何消息都不会发送到服务器(从技术上讲,它们会在发送之前从发送缓冲区中清除)。有用。


FYI, another possibility would be to just not call .emit() when the socket is not connected. So, you could just create your own function or method that would only try to .emit() when the socket is actually connected, thus nothing would ever get into the sendBuffer.

仅供参考,另一种可能性是在未连接套接字时不调用.emit()。因此,您可以创建自己的函数或方法,只有在套接字实际连接时才会尝试.emit(),因此什么都不会进入sendBuffer。

Socket.prototype.emitWhenConnected = function(msg, data) {
    if (this.connected) {
        return this.emit(msg, data);
    } else {
        // do nothing?
        return this;
    }
}

Or, more dangerously, you could override .emit() to make it work this way (not my recommendation).

或者,更危险的是,您可以覆盖.emit()以使其以这种方式工作(不是我的推荐)。

#1


15  

When all else fails with open source libraries, you go study the code and see what you can figure out. After spending some time doing that with the socket.io source code...

当所有其他方法都失败了开源库时,你会去研究代码,看看你能弄清楚什么。花了一些时间用socket.io源代码做了...

The crux of the issue seems to be this code that is here in socket.emit():

这个问题的关键似乎是socket.emit()中的代码:

  if (this.connected) {
    this.packet(packet);
  } else {
    this.sendBuffer.push(packet);
  }

If the socket is not connected, all data sent via .emit() is buffered in the sendBuffer. Then, when the socket connects again, we see this:

如果未连接套接字,则通过.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 = [];
};

So, this fully explains why it buffers all data sent while the connection is down and then sends it all upon reconnect.

因此,这完全解释了为什么它在连接断开时缓冲所有发送的数据,然后在重新连接时发送所有数据。

Now, as to how to prevent it from sending this buffered data, here's a theory that I will try to test later tonight when I have more time.

现在,至于如何防止它发送这个缓冲数据,这是一个理论,我将在今晚晚些时候尝试测试我有更多时间。

Two things look like they present an opportunity. The socket notifies of the connect event before it sends the buffered data and the sendBuffer is a public property of the socket. So, it looks like you can just do this in the client code (clear the buffer upon connect):

两件事看起来像是一个机会。套接字在发送缓冲数据之前通知connect事件,sendBuffer是套接字的公共属性。所以,看起来你可以在客户端代码中执行此操作(在连接时清除缓冲区):

// clear previously buffered data when reconnecting
socket.on('connect', function() {
    socket.sendBuffer = [];
});

I just tested it, and it works just fine. I have a client socket that sends an increasing counter message to the server every second. I take the server down for 5 seconds, then when I bring the server back up before adding this code, all the queued up messages arrive on the server. No counts are missed.

我刚试过它,它运行得很好。我有一个客户端套接字,每秒向服务器发送一个增加的计数器消息。我将服务器关闭了5秒钟,然后当我在添加此代码之前重新启动服务器时,所有排队的消息都会到达服务器上。没有错过任何计数。

When, I then add the three lines of code above, any messages sent while the server is down are not sent to the server (technically, they are cleared from the send buffer before being sent). It works.

然后,当我添加上面三行代码时,服务器关闭时发送的任何消息都不会发送到服务器(从技术上讲,它们会在发送之前从发送缓冲区中清除)。有用。


FYI, another possibility would be to just not call .emit() when the socket is not connected. So, you could just create your own function or method that would only try to .emit() when the socket is actually connected, thus nothing would ever get into the sendBuffer.

仅供参考,另一种可能性是在未连接套接字时不调用.emit()。因此,您可以创建自己的函数或方法,只有在套接字实际连接时才会尝试.emit(),因此什么都不会进入sendBuffer。

Socket.prototype.emitWhenConnected = function(msg, data) {
    if (this.connected) {
        return this.emit(msg, data);
    } else {
        // do nothing?
        return this;
    }
}

Or, more dangerously, you could override .emit() to make it work this way (not my recommendation).

或者,更危险的是,您可以覆盖.emit()以使其以这种方式工作(不是我的推荐)。