Socket.io: 服务器执行 socket.disconnect( true ) 后客户端重新连接的正确方法

创建于 2016-03-09  ·  35评论  ·  资料来源: socketio/socket.io

服务器:节点 + socket.io

var io = require( 'socket.io' )( 3000 );

io.on( 'connection', function ( socket ) ...

// at some point if client auth fails, server may kick him out:

socket.disconnect( true );

客户端:html/js + socket.io 1.4.5

socket = io.connect( 'http://127.0.0.1:3000', {
    reconnection: true,
    reconnectionDelay: 1000,
    reconnectionDelayMax : 5000,
    reconnectionAttempts: 99999
} );

socket.on( 'connect', function () {
    console.log( 'connected to server' );
} );

socket.on( 'disconnect', function () {
    console.log( 'disconnected to server' );
} );

以上是简化的,但这是基础。 如果我在服务器关闭时启动客户端,重新连接工作正常。 客户端尝试连接到服务器,当我最终启动服务器时,连接就建立起来了。

在某些时候,可能会发生服务器决定与客户端断开连接的情况,主要是因为他注销使令牌无效并且对数据库的查询告诉这样做,或者身份验证令牌已过期或其他什么。

在这种情况下,我希望恢复客户端轮询的服务器,因为用户可能想再次登录并且他有权再次连接到服务器。

如果我在浏览器中刷新页面(客户端),它可以正常工作,但这是一个丑陋的解决方案。

我认为原因是在执行 disconnect() 后“Manager.skipReconnect”属性设置为 true,所以我在问在服务器断开客户端连接后重新启动客户端重新连接轮询的正确方法是什么。

在stackoverflow上找到了一些关于这个的答案,但都没有成功,所有的东西都要在客户端执行:

  • socket.io.reconnect();
  • socket.socket.reconnect(); // ??
  • socket = io.connect( ' http://127.0.0.1 :3000', ... // 重新调用连接片段似乎是个坏主意

你能帮我解决这个问题吗?

谢谢

最有用的评论

目前,我是这样管理的,它似乎很稳定:

客户

var app = {
...
socket: null,
connect: function() {
  var self = this;
  if( self.socket ) {
    self.socket.destroy();
    delete self.socket;
    self.socket = null;
  }
  this.socket = io.connect( 'http://127.0.0.1:3000', {
    reconnection: true,
    reconnectionDelay: 1000,
    reconnectionDelayMax : 5000,
    reconnectionAttempts: Infinity
  } );
  this.socket.on( 'connect', function () {
    console.log( 'connected to server' );
  } );
  this.socket.on( 'disconnect', function () {
    console.log( 'disconnected from server' );
    window.setTimeout( 'app.connect()', 5000 );
  } );
}
...
} // var app

所有35条评论

目前,我是这样管理的,它似乎很稳定:

客户

var app = {
...
socket: null,
connect: function() {
  var self = this;
  if( self.socket ) {
    self.socket.destroy();
    delete self.socket;
    self.socket = null;
  }
  this.socket = io.connect( 'http://127.0.0.1:3000', {
    reconnection: true,
    reconnectionDelay: 1000,
    reconnectionDelayMax : 5000,
    reconnectionAttempts: Infinity
  } );
  this.socket.on( 'connect', function () {
    console.log( 'connected to server' );
  } );
  this.socket.on( 'disconnect', function () {
    console.log( 'disconnected from server' );
    window.setTimeout( 'app.connect()', 5000 );
  } );
}
...
} // var app

使用类似的方法:

  this.socket = io.connect( 'ws://127.0.0.1:3000', {
    reconnection: true,
    reconnectionDelay: 1000,
    reconnectionDelayMax : 5000,
    reconnectionAttempts: Infinity
  } );

不幸的是,这会导致套接字使用 http 协议,而不是 Web 套接字。

仍在寻找一种用于持久 Web 套接字连接的好方法。

我错过了什么吗???

也有兴趣解决这个问题。

socket.connect()
在版本 1.5.1 上为我工作。 希望有帮助。

@sconway你能启发我们吗? 任何代码都可以?

你好呀,

有同样的问题,发现这个解决方案,目前正在测试,似乎要么是一个强大的解决方案,要么是一个强大的解决方法......(两者都提供)

http://stackoverflow.com/questions/10437584/socket-io-reconnect

我们可以在 socket.io 本身中解决这个问题吗?

我升级到 2.0.3 版,它的默认自动重新连接设置有效,这里没有问题。

当服务器或客户端调用 disconnect() 方法时,客户端销毁套接字,删除所有事件处理程序,管理器将其从连接数组中删除。 当断开连接是出于其他原因时,不会发生这种情况。
一个很好的解决方法可以读取原因参数
.on('disconnect', reason => { if(reason === 'io server disconnect') { //you should renew token or do another important things before reconnecting socket.connect(); } });
或者更好地检查套接字是否仍在管理器的连接列表中
.on('disconnect', () => { if(socket.io.connecting.indexOf(socket) === -1){ //you should renew token or do another important things before reconnecting socket.connect(); } })

我像@DrLightman一样

var WebSocketServer = {
    isConnected: false,
    socket: null,
    interval: null,
    connect() {
        if (this.socket) {
            this.socket.destroy();
            delete this.socket;
            this.socket = null;
        }
        this.socket = io.connect('http://localhost:9010', {
            reconnection: false
        });
        this.socket.on('connect', () => {
            this.isConnected = true;
            this.socket.emit('authentication', { user_id: 2751, token: "abc" });
            this.socket.on('authenticated', function() {

            });
        });

        this.socket.on('disconnect', () => {
            this.isConnected = false;
            this.interval = window.setInterval(() => {
                if (this.isConnected) {
                    clearInterval(this.interval);
                    this.interval = null;
                    return;
                }
                WebSocketServer.connect()
            }, 5000);
        });

        return this.socket;
    }
}

var socket = WebSocketServer.connect();

@DrLightman这就是我的做法并且在浏览器或 Android/IOS 应用程序中完美运行
var io= new socketio.connect('http://192.168.43.79:3000',{'forceNew':true});

@pablodgonzalez我有同样的问题,您的解决方案有效吗?

@programmerCs是的,是的。 在生产中没有检测到问题。

这个问题解决了我的很多问题
谢谢大家

当我想强制客户端刷新它的令牌时遇到了同样的问题,因为它在连接到服务器时过期了。

我最终向客户端发送了一个事件,要求他刷新它的令牌。 这样做不会关闭任何套接字,因此可以避免出现问题并且可以正常工作!

...现在是时候将其推向生产了! :cold_sweat: :smirk:

似乎最简单的解决方案是侦听来自发射器的“断开连接”事件并调用 setTimeout() 函数,但是客户端在与服务器断开连接时可以创建的事件呢? 似乎在客户端上广播任何发射之前,它总是需要执行额外的检查是否建立了连接。

@qassa如果您需要一些关于发射的确认,您应该使用回调参数。 相反,如果您需要保证事件的接收,则不应使用 socket.io,而应使用一些队列库/协议,例如 Mosque/mqtt 或其他任何东西。
setTimeout 是一个选项,但(由服务器或客户端)断开的套接字是一个很快被破坏的套接字。 所以,如果你需要保证简单快速的重新连接,如果你有套接字对象实例并且可以调用connect(),为什么要使用setTimeout?

项目中的某个人真的需要记录这个……

让我明白这一点,服务器是否出于特定原因或由于网络连接丢失而断开客户端? 如果它只是网络,那么 Socketio(client) 将无限期地尝试重新连接! ,如果这样配置io=new socketio(‘http://yourserver.com’, {'forceNew':true});无论哪种方式它仍然会重新连接,但是如果你把一个监听器从服务器断开,只需在客户端调用io.disconnect()

来自:CxRes [mailto:[email protected]]
发送时间:2018 年 2 月 1 日晚上 09:50
至:socketio/socket.io [email protected]
抄送:devyaz [email protected] ; 评论[email protected]
主题: Re: [socketio/socket.io] 服务器执行 socket.disconnect( true ) 后客户端重新连接的正确方法 (#2476)

项目中的某个人真的需要记录这个……


您收到此消息是因为您发表了评论。
直接回复本邮件,在 GitHub 上查看https://github.com/socketio/socket.io/issues/2476#issuecomment-362381171 ,或者将线程静音https://github.com/notifications/unsubscribe-auth/ ATfQSQQ1LJ90E6FqsdmiMktpp2AdoLuxks5tQhVQgaJpZM4HsVs7https://github.com/notifications/beacon/ATfQSYqwkgtrHZk9FASNZUl69ps9ZYYCks5tQhVQgaJpZM4HsVs7.gif

@devyaz我爱你

文档已更新为@pablodgonzalez的回答: https :

非常感谢!

使用0.8.3版本的 io.socket 删除新版本 1.0.0

compile('io.socket:socket.io-client:0.8.3') {
    exclude group: 'org.json', module: 'json'
}

使用类似的方法:

  this.socket = io.connect( 'ws://127.0.0.1:3000', {
    reconnection: true,
    reconnectionDelay: 1000,
    reconnectionDelayMax : 5000,
    reconnectionAttempts: Infinity
  } );

不幸的是,这会导致套接字使用 http 协议,而不是 Web 套接字。

仍在寻找一种用于持久 Web 套接字连接的好方法。

我错过了什么吗???

使用 wss://

使用类似的方法:

  this.socket = io.connect( 'ws://127.0.0.1:3000', {
    reconnection: true,
    reconnectionDelay: 1000,
    reconnectionDelayMax : 5000,
    reconnectionAttempts: Infinity
  } );

不幸的是,这会导致套接字使用 http 协议,而不是 Web 套接字。
仍在寻找一种用于持久 Web 套接字连接的好方法。
我错过了什么吗???

使用 wss://

你好,兄弟。怎么可能,如果只使用 wss。它只是作为持久的 web 套接字连接工作,有同样的问题,关于只保持和快速重新连接 ws 不轮询。

当服务器或客户端调用 disconnect() 方法时,客户端销毁套接字,删除所有事件处理程序,管理器将其从连接数组中删除。 当断开连接是出于其他原因时,不会发生这种情况。
一个很好的解决方法可以读取原因参数

.on('disconnect', reason => { 
  if(reason === 'io server disconnect') {
    //you should renew token or do another important things before reconnecting
    socket.connect();
  }
});

或者更好地检查套接字是否仍在管理器的连接列表中

.on('disconnect',  () => {
  if(socket.io.connecting.indexOf(socket) === -1){
    //you should renew token or do another important things before reconnecting
    socket.connect();
  }
})

您能否详细说明为什么最好检查套接字是否仍在管理器的连接列表中? 更新后的文档仅采用了您的第一个解决方案,即检查断开连接的原因。 谢谢。

@emclab ,只是因为如果在较新的版本中开发人员添加了一些新的原因,并且对于您的情况来说“原因”并不重要,那么只需在连接列表中搜索套接字即可。 如果不存在,则必须手动重新连接。
在某些情况下,知道原因很重要,并且是更强大的情况,阅读并采取相应的行动,但可能不是最常见的。
免责声明:如果您采用第二种方式,则在较新版本中重构或机制的某些更改并不安全,因此它并没有好多少,但要简单得多。
问候!

我无法将断开连接到离子应用程序中。 我有 socket.on 到提供者公共页面的构造函数中。 我想从调用应用程序注销的同一文件上断开套接字到一个函数的连接。

但我能够断开插座。 我是多个 socket.on('event') 多次发射到应用程序中。
谁能帮我吗?

Socket.disconnect() 应该做

在 2019 年 11 月 11 日星期一 06:16 krunal9421, notifications @github.com 写道:

我无法将断开连接到离子应用程序中。 我有
socket.on 到 provider 中公共页面的构造函数中。 我想要
断开套接字连接到应用程序所在的同一文件上的函数
注销被调用。

但我能够断开插座。 我是多个 socket.on('event')
在多次发射到应用程序中。
谁能帮我吗?


你收到这个是因为你被提到了。
直接回复本邮件,在GitHub上查看
https://github.com/socketio/socket.io/issues/2476?email_source=notifications&email_token=AE35ASNI2K4DWOB4P2HPSATQTDMC7A5CNFSM4B5RLM52YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVX5WWJ280000000000000000000000000000250000000000000000020000500007
或取消订阅
https://github.com/notifications/unsubscribe-auth/AE35ASJPORGOSYQAEJEHHG3QTDMC7ANCNFSM4B5RLM5Q
.

@devyaz我无法使用 socket.disconnect() 断开套接字。
我已经与此分享了我的示例代码。
https://i.stack.imgur.com/wrIEv.png。

我已将代码写入公共文件。

您是否尝试与服务器或用户端断开连接? 即服务器应该
断开用户。 因为如果服务器丢失客户端,它会触发断开连接
事件。 但是客户端可以通过调用与服务器断开连接
socket.disconnect

在 2019 年 11 月 20 日星期三 05:39 krunal9421, notifications @github.com 写道:

@devyaz https://github.com/devyaz我无法断开套接字
使用 socket.disconnect()。
我已经与此分享了我的示例代码。
https://i.stack.imgur.com/wrIEv.png。

我已将代码写入公共文件。


你收到这个是因为你被提到了。
直接回复本邮件,在GitHub上查看
https://github.com/socketio/socket.io/issues/2476?email_source=notifications&email_token=AE35ASK4NY4SKG5JWSBDKCTQUSWNVA5CNFSM4B5RLM52YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXWZHJ820000000000000000000000000000000000000000000000000000000000001
或取消订阅
https://github.com/notifications/unsubscribe-auth/AE35ASIFTISGTIAQQ7UKCJDQUSWNVANCNFSM4B5RLM5Q
.

在客户端使用它。

在您的注销功能中执行this.socketstatus.disconnect() ,我认为
你应该删除函数“.on(“connected”,.....)”

2019 年 11 月 22 日星期五 11:50 krunal9421, notifications @github.com 写道:

在客户端使用它。


你收到这个是因为你被提到了。
直接回复本邮件,在GitHub上查看
https://github.com/socketio/socket.io/issues/2476?email_source=notifications&email_token=AE35ASJTREAYRMF4THBK3FDQU6TOLA5CNFSM4B5RLM52YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXWSZ5G00000MVBW63LNMVXWZHJ7056000
或取消订阅
https://github.com/notifications/unsubscribe-auth/AE35ASJGKVGVUQNK454C63DQU6TOLANCNFSM4B5RLM5Q
.

失去连接后,套接字重新连接到服务器。 之后,它一直显示_io.socket.engineio.client.EngineIOException: xhr post error_ in Android
StackOverflow 的大多数答案都不起作用。
我被这个问题困住了 T_T .... 请帮帮我!

我正在尝试在我的 node.js + javaScript wepapp 中实现此代码,但是当我的手机浏览器在后台,在非活动选项卡或锁定屏幕中时,它会在几分钟后断开连接。

我试图在断开连接时重新连接到套接字(使用ping timeouttransport closed响应),但这是不可能的。 这是手机浏览器的正常行为吗? 因为在笔记本电脑或台式机浏览器中按预期工作。

谁能帮我?

谢谢

@asiermusa,但在网络中,您必须使用网络工作者来避免暂停进程。 我真的不知道这是否足以实现这一目标。

干杯!

此页面是否有帮助?
0 / 5 - 0 等级