принудительно отключить клиента от сервера с помощью socket.io и nodejs

117

Есть ли способ отключить клиента с SocketIO и буквально закрыть соединение? Итак, если кто-то подключен к моему серверу, и я хочу закрыть соединение между ним и моим сервером, как я могу это сделать?

Дэниел Кенни
источник

Ответы:

146

Изменить: теперь это возможно

Теперь вы можете просто позвонить socket.disconnect()на стороне сервера .

Мой первоначальный ответ:

Пока это невозможно.

Если вам это тоже нужно, проголосуйте / прокомментируйте этот вопрос .

NH2
источник
Итак, я делаю это, и это заставляет клиента отключиться, к сожалению, похоже, что клиент просто немедленно подключается снова. Я неправильно понимаю, что происходит, или это ожидаемое поведение?
kybernetikos
@kybernetikos Да, этого я и ожидал - в конце концов, клиент может сам выбирать, что ему делать. Часто вы хотите отключить другую сторону от текущего соединения, скажем, из-за тайм-аута аутентификации - повторное соединение после этого, вероятно, даже будет желательным.
nh2
Итак, знаете ли вы, как сказать клиенту: «Уходи, и я действительно серьезно»? Я думаю с точки зрения определения того, что клиент ведет себя плохо, и не хочу, чтобы он использовал ресурсы на моем сервере.
kybernetikos
@kybernetikos Нет, вы не можете этого сделать (обычно). Однако, если вы программируете на стороне клиента, вы, конечно, можете реализовать любую логику, которую хотите, например, запретить повторное подключение. В противном случае придется неоднократно кикать пользователей или, если это действительно необходимо, прибегать к стандартным методам блокировки; чем ниже уровень их реализации (например iptables), тем больше ресурсов вы сэкономите. В большинстве случаев достаточно просто пнуть клиента, так как socketio не подключается так быстро, и если кто-то действительно хочет сделать DoS-атаку на вас, у них все равно есть другие способы (например, загрузка страниц от вас).
nh2
1
@ManishSapkal Для этого вам, вероятно, следует открыть новый вопрос, он не подходит для комментариев.
nh2
15

socket.disconnect() может использоваться только на стороне клиента, но не на стороне сервера.

Client.emit('disconnect')запускает событие отключения на сервере, но не отключает клиента. Клиент не знает об отключении.

Таким образом, остается вопрос: как заставить клиента отключиться от сервера?

Фабьен
источник
1
В Client.emit('disconnect')последних версиях socket.io вам больше не нужно вызывать вручную, теперь есть серверная часть socket.disconnect()(см. Мой ответ).
nh2
5
Из-за недавних обновлений ваш ответ теперь неверен, поэтому -1.
corazza
Я согласен, этот ответ больше недействителен, потому что теперь его socket.disconnect()можно использовать и на стороне сервера.
Василис Барзокас
@VassilisBarzokas Что, если мне нужен обратный вызов и передать некоторые параметры в обратный вызов после завершения disconnect()функции?
newguy
создайте согласованный набор сообщений, в котором одна сторона информирует другую сторону о своем желании отключиться, затем делает то, что вам нужно, а затем фактически отключается.
Mike 'Pomax' Kamermans
8

Есть ли причина, по которой сервер не может отправлять клиенту сообщение, которое заставляет его вызывать функцию отключения?

На клиенте:

socket.emit('forceDisconnect');

На сервере:

socket.on('forceDisconnect', function(){
    socket.disconnect();
});
quahada
источник
7
Потому что на клиентский код нельзя полагаться, чтобы он работал так, как вы хотите. Пользователи могут легко его изменить.
Kaustubh Karkare 08
4

Предполагая, что ваш сокет назван socket, используйте:

socket.disconnect()
Erik
источник
2
К сожалению, это не работает. Я пытаюсь закрыть соединение с конкретным клиентом со стороны сервера.
Дэниел Кенни
4

Для тех, кто нашел это в гугле - прямо сейчас есть решение:

Socket.disconnect()пинает клиента (на стороне сервера). У клиента нет шансов оставаться на связи :)

Саша Гелих
источник
Как найти сокет пользователя, который отключен от сервера?
Маниш Сапкал
Маниш: прослушайте disconnectсобытие сокета, чтобы узнать, отключился ли он. Тоже может быть closeсобытие, я не совсем уверен. См. Документацию socket.io для получения дополнительной информации об этом.
Sascha Gehlich
3

В моем случае я хотел разорвать базовое соединение, и в этом случае мне пришлось позвонить, socket.disconnect(true)как вы можете видеть, это необходимо из источника здесь

Дункан
источник
2

client._onDisconnect() должно сработать

Emmerman
источник
1
Это прекрасно работает .. Я поддерживаю свое собственное отображение клиентов ... используя это отображение ... легко отключаю клиентов .. ура
Arenstar
1

Socket.io использует шаблон EventEmitter для отключения / подключения / проверки пульса, чтобы вы могли это сделать. Client.emit('disconnect');

Энтони Влодарски
источник
1

У меня это не сработало :

`socket.disconnect()` 

Это сработало для меня:

socket.disconnect(true)

При передаче trueбудет закрыто базовое соединение с клиентом, а не только пространство имен, которое клиент подключен к документации Socket IO .


Пример использования: клиент подключился к серверу веб-сокетов с недопустимым токеном доступа (токен доступа передан серверу веб-сокетов с параметрами подключения). Сервер веб-сокетов уведомляет клиента о том, что он собирается закрыть соединение из-за его недопустимого токена доступа:

// (1) the server code emits
socket.emit('invalidAccessToken', function(data) {
    console.log(data);       // (4) server receives 'invalidAccessTokenEmitReceived' from client
    socket.disconnect(true); // (5) force disconnect client 
});

// (2) the client code listens to event
// client.on('invalidAccessToken', (name, fn) => { 
//     // (3) the client ack emits to server
//     fn('invalidAccessTokenEmitReceived');
// });
Баран Эмре
источник
0

Я использую client.emit('disconnect')+ client.removeAllListeners()для подключенного клиента, чтобы игнорировать все события после отключения

летчик
источник
0

Я использую на стороне клиента socket.disconnect();

client.emit('disconnect') didnt work for me
yonia
источник
0

использование:

socket.Disconnect () // ок

не используй :

socket.disconnect ()

м-тек
источник
0

Вы можете socket = undefinedстереть, какой сокет вы подключили. Итак, когда вы хотите подключиться, сделайте сокет (url)

Так это будет выглядеть так

const socketClient = require('socket.io-client');

let socket;

// Connect to server
socket = socketClient(url)

// When want to disconnect
socket = undefined;
Саураб Гупта
источник
-1

Добавьте новые соединения сокетов в массив, а затем, когда вы хотите закрыть все - пропустите их и отключите. (на стороне сервера)

var socketlist = [];

   io.sockets.on('connection', function (socket) {
        socketlist.push(socket);  
        //...other code for connection here..
   });


    //close remote sockets
    socketlist.forEach(function(socket) {        
        socket.disconnect();                      
    });    
PodTech.io
источник