Socket.io: Правильный способ повторного подключения клиента после того, как сервер выполнит socket.disconnect (true)

Созданный на 9 мар. 2016  ·  35Комментарии  ·  Источник: socketio/socket.io

Сервер : node + 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' );
} );

Сказанное выше упрощено, но это основа. Повторное подключение работает нормально, если я запускаю клиента, когда сервер не работает. Клиент пытается подключиться к серверу, и когда я наконец запускаю сервер, соединение устанавливается.

В какой-то момент может случиться так, что сервер решит отключить клиента, в основном из-за того, что он вышел из системы, сделав токен недействительным, и запрос в базе данных сообщает об этом, или истек срок действия токена аутентификации или что-то еще.

В этом случае я бы хотел восстановить опрос сервера клиентом, потому что пользователь может захотеть снова войти в систему, и у него есть права на повторное подключение к серверу.

Если я обновляю страницу (клиент) в браузере, все работает нормально, но это уродливое решение.

Я думаю, что причина в том, что для свойства «Manager.skipReconnect» установлено значение true после выполнения disconnect (), поэтому я спрашиваю, как правильно инициировать повторный опрос клиента после того, как сервер отключит клиента.

Нашел несколько ответов на 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, а не веб-сокеты.

Все еще ищу хороший подход для постоянного подключения к веб-сокету.

Я что-то пропустил ???

Также интересует решение этого.

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:: ухмылка:

Похоже, что самое простое решение - прослушать событие «отключить» от эмиттера и вызвать функцию setTimeout (), но как насчет событий, которые клиент может создавать, когда он отключен от сервера? Похоже, что всегда нужно выполнять дополнительную проверку, установлено ли соединение, прежде чем транслировать любое излучение на клиенте.

@qassa, если вам нужно какое-то подтверждение об испускании, вы должны использовать параметр обратного вызова. Вместо этого, если вам нужно гарантировать получение события, вы должны использовать не socket.io, а какую-то библиотеку / протокол очереди, например mosquito / mqtt или что-то еще.
setTimeout - это опция, но сокет, отключенный (сервером или клиентом), скоро будет уничтожен. Итак, если вам нужно гарантировать простое и быстрое переподключение, зачем использовать setTimeout, если у вас еще есть экземпляр объекта сокета и вы можете вызвать connect ()?

Кому-то из проекта ДЕЙСТВИТЕЛЬНО НУЖНО ЗАДокументировать это ...

Позвольте мне понять это прямо: сервер отключает клиента по определенной причине или из-за потери сетевого соединения? Если это просто сеть, то Socketio (клиент) будет бесконечно пытаться повторно подключиться! , если настроен так io=new socketio(‘http://yourserver.com’, {'forceNew':true}); любом случае он все равно будет повторно подключаться, но если вы поместите прослушиватель на отключение от сервера, просто вызовите io.disconnect() на клиенте

От: CxRes [mailto: [email protected]]
Отправлено: 1 февраля 2018 г., 21: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/ ATfQSQQ1LJ90E6FqsdmiMktpp2AdoLuxks5tQhVQgaJpZM4HsVs7 . https://github.com/notifications/beacon/ATfQSYqwkgtrHZk9FASNZUl69ps9ZYYCks5tQhVQgaJpZM4HsVs7.gif

@devyaz я люблю тебя

Документация была обновлена ответом @pablodgonzalez : https://github.com/socketio/socket.io-client/commit/afb952d854e1d8728ce07b7c3a9f0dee2a61ef4e

Большое спасибо!

Используйте 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, а не веб-сокеты.

Все еще ищу хороший подход для постоянного подключения к веб-сокету.

Я что-то пропустил ???

используйте wss: //

Используя аналогичный подход:

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

К сожалению, это заставляет сокет использовать протокол http, а не веб-сокеты.
Все еще ищу хороший подход для постоянного подключения к веб-сокету.
Я что-то пропустил ???

используйте wss: //

привет, братан. Как может быть так, что если просто использовать wss.it, просто работать как постоянное соединение с веб-сокетом, у вас есть тот же вопрос о том, чтобы просто сохранить и быстро восстановить сеть с 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 () должен делать

В пн, 11 ноября 2019 г., 06:16 krunal9421, [email protected] написал:

Я не могу отключить розетку от ионного приложения. у меня есть
socket.on в конструктор общей страницы в провайдерах. я хочу
отключить сокет в функции в том же файле, откуда приложение
Выход из системы называется.

Но я могу отключить розетку. У меня несколько socket.on ('event')
при многократном выпуске в приложение.
Может кто-нибудь мне помочь?

-
Вы получаете это, потому что вас упомянули.
Ответьте на это письмо напрямую, просмотрите его на GitHub
https://github.com/socketio/socket.io/issues/2476?email_source=notifications&email_token=AE35ASNI2K4DWOB4P2HPSATQTDMC7A5CNFSM4B5RLM52YY3PNVWWK3TUL52HS4DFMVREXG43
или отказаться от подписки
https://github.com/notifications/unsubscribe-auth/AE35ASJPORGOSYQAEJEHHG3QTDMC7ANCNFSM4B5RLM5Q
.

@devyaz Я не могу отключить сокет с помощью socket.disconnect ().
Я поделился своим образцом кода с этим.
https://i.stack.imgur.com/wrIEv.png.

Я написал код в общий файл.

Вы пытаетесь отключиться от сервера или пользователя? т.е. сервер должен
отключить пользователя. Потому что, если сервер теряет клиента, он вызывает отключение
мероприятие. Но клиент может отключиться от сервера, позвонив
socket.disconnect

В среду, 20 ноября 2019 г., 05:39 krunal9421, [email protected] написали:

@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=AE35ASK4NY4SKG5JWSBDKCTQUSWNVA5CNFSM4B5RLM52YY3PNVWWK3TUL52HS443DFVREX22PNVWWK3TUL52HS443DFVREXWDWWWK3TUL52HS443DFVREX22
или отказаться от подписки
https://github.com/notifications/unsubscribe-auth/AE35ASIFTISGTIAQQ7UKCJDQUSWNVANCNFSM4B5RLM5Q
.

используя это на стороне клиента.

Сделайте this.socketstatus.disconnect() в своей функции выхода, и я думаю
вам следует удалить функцию ".on (" connected, .....) "

Пт, 22 ноя 2019, 11:50 krunal9421, [email protected] написали:

используя это на стороне клиента.

-
Вы получаете это, потому что вас упомянули.
Ответьте на это письмо напрямую, просмотрите его на GitHub
https://github.com/socketio/socket.io/issues/2476?email_source=notifications&email_token=AE35ASJTREAYRMF4THBK3FDQU6TOLA5CNFSM4B5RLM52YY3PNVWWWK3TUL52HS4DFVREXG43VLWWK3TUL52HS4DFVREXG43VLWWK3TUL52HS4DFVREXG43V5
или отказаться от подписки
https://github.com/notifications/unsubscribe-auth/AE35ASJGKVGVUQNK454C63DQU6TOLANCNFSM4B5RLM5Q
.

После потери соединения сокет повторно подключается к серверу. После этого он продолжает показывать _io.socket.engineio.client.EngineIOException: xhr post error_ в Android .
Большинство ответов StackOverflow не работают.
Я застрял с этой проблемой T_T .... Помогите, пожалуйста!

Я пытаюсь реализовать этот код в моем node.js + javaScript wepapp, но когда браузер моего телефона находится в фоновом режиме, на неактивной вкладке или заблокированном экране, он отключается через несколько минут.

Я попытался повторно подключиться к сокету, когда он отключен (с ответами ping timeout или transport closed ), но это невозможно. Это нормальное поведение в браузерах телефона? потому что в браузерах ноутбука или настольного компьютера все работает так, как ожидалось.

Может кто-нибудь мне помочь?

Спасибо

Привет, @asiermusa, но в сети вы должны использовать веб-воркер, чтобы не приостанавливать процесс. Я искренне не знаю, достаточно ли этого для этого.

ваше здоровье!

Была ли эта страница полезной?
0 / 5 - 0 рейтинги