socket.io在x秒/第一次失败尝试获得响应后停止重新发出事件 [英] socket.io stop re-emitting event after x seconds/first failed attempt to get a response

查看:144
本文介绍了socket.io在x秒/第一次失败尝试获得响应后停止重新发出事件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

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 ).

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

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源代码完成...

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.emit()

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

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

如果套接字未连接,则所有数据都通过 .emit()缓冲在 sendBuffer 中。然后,当套接字再次连接时,我们看到:

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:

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.

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

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):

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

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

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.

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

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.

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

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.

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

或者,更危险的是,你可以覆盖 .emit()让它以这种方式工作(不是我的建议)。

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

这篇关于socket.io在x秒/第一次失败尝试获得响应后停止重新发出事件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆