Як надіслати повідомлення певному клієнту за допомогою socket.io


96

Я починаю з socket.io + node.js, я знаю, як надіслати повідомлення локально та socket.broadcast.emit()функцію трансляції : - всі підключені клієнти отримують одне і те ж повідомлення.

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


На жаль, psiphi75, але це посилання не відповідає на мою відповідь і не є дублікатом запитання.
Nizar B.

1
@ psiphi75, це ніяк не дублікат
softvar

1
Не витримує таких людей, як @psiphi. Ви навіть розробник? Як специфічне для HTML5 питання стосується автономної бібліотеки? І що того варте, WebSockets - НЕ Socket.io. Socket.io - це бібліотека, яка може ВИКОРИСТОВУВАТИ WebSockets, але я відступаю. Це також більш конкретне питання стосовно бібліотеки щодо надсилання даних лише конкретним клієнтам, а не про саму технологію.
Леві Робертс,


@ bugwheels94 Неправда, ця публікація від 2011 року, і оскільки nodejs мав купу змін по коду. ця публікація, безумовно, є правильним запитанням / відповіддю на це питання.
Нізар Б.

Відповіді:


102

Коли користувач підключається, він повинен надіслати на сервер повідомлення з іменем користувача, яке повинно бути унікальним, як електронна пошта.

Пара імені користувача та сокета повинна зберігатися в такому об'єкті:

var users = {
    'userA@example.com': [socket object],
    'userB@example.com': [socket object],
    'userC@example.com': [socket object]
}

На клієнті передайте об’єкт на сервер із такими даними:

{
    to:[the other receiver's username as a string],
    from:[the person who sent the message as string],
    message:[the message to be sent as string]
}

На сервері прослуховуйте повідомлення. Коли повідомлення отримано, передайте дані одержувачу.

users[data.to].emit('receivedMessage', data)

На клієнті прослуховуйте викиди з сервера під назвою 'receivedMessage', і, читаючи дані, ви можете обробляти, від кого вони надійшли, і повідомлення, яке було надіслано.


26
Якщо ви використовуєте це рішення, то вам слід зрозуміти: 1. Коли користувач відключається, вам потрібно очистити об'єкт "користувачі". 2. Він не підтримує друге з'єднання - наприклад, з іншого браузера. Отже, якщо користувач підключається з іншого браузера - старе підключення буде замінено.
Володимир Курійов

1
як би ви зберегли об'єкт socket у сховищі даних? Я припускаю, що це не працює, якщо у вас є більше ніж один процес вузла.
chovy

@chovy ви повинні використовувати redis. Перевірте це github.com/LearnBoost/Socket.IO/wiki/Configuring-Socket.IO
Володимир Курійов

11
Я пропоную не використовувати це рішення. Зрештою, я витратив багато часу, намагаючись подолати обмеження цього підходу. Дивіться рішення @ az7ar та це пояснення, чому це краще .
Daniel Que

@DanielQue +1. Набагато краще, що використовується рідна функціональність. Дякую!
Аарон Лелев'є

275

Ви можете використовувати кімнати socket.io. З боку клієнта видайте подію ("приєднатися" в даному випадку може бути будь-якою) з будь-яким унікальним ідентифікатором (електронна пошта, ідентифікатор).

Сторона клієнта:

var socket = io.connect('http://localhost');
socket.emit('join', {email: user1@example.com});

Тепер з боку сервера використовуйте цю інформацію, щоб створити унікальну кімнату для цього користувача

Сторона сервера:

var io = require('socket.io').listen(80);

io.sockets.on('connection', function (socket) {
  socket.on('join', function (data) {
    socket.join(data.email); // We are using room of socket io
  });
});

Отже, тепер кожен користувач приєднався до кімнати, названої на електронну адресу користувача. Отже, якщо ви хочете надіслати конкретному користувачеві повідомлення, вам просто потрібно

Сторона сервера:

io.sockets.in('user1@example.com').emit('new_msg', {msg: 'hello'});

Останнє, що залишилося зробити на стороні клієнта, - це прослухати подію "new_msg".

Сторона клієнта:

socket.on("new_msg", function(data) {
    alert(data.msg);
}

Сподіваюся, ідея вам зрозуміла


3
будь ласка, змініть цей рядок io.socket.in ('user1@example.com '). emit (' new_msg ', {msg:' hello '}); наприклад io.sockets.in ('user1@example.com '). emit (' new_msg ', {msg:' hello '});
silvesterprabu

42
Ця відповідь набагато краща за прийняту в даний час відповідь. Ось чому: 1) Вам не потрібно керувати та очищати глобальний масив клієнтів. 2) Це працює, навіть якщо у користувача на одній сторінці відкрито кілька вкладок. 3) Його можна легко розширити для роботи з кластером вузлів (кілька процесів) з socket.io-redis.
Daniel Que

2
як ти робиш {email: user1@example.com}різним для всіх підключень, чи не всі клієнти, які переходять до програми, мають користувача, user1@example.comяк я user2@example.comможу зробити його користувачем для другого клієнта, який підключається, щоб я міг мати різні кімнати. вибачте, якщо це докучливе питання.
jack blank

2
сподобалося рішення, але я вважаю, що тут порушена безпека. Що робити, якщо я змінив електронну адресу в сценарії на стороні клієнта. Тепер я можу читати й інші приватні повідомлення. Що ти кажеш?
Gopinath Shiva

3
це не обов’язково електронна пошта. Я згадав якийсь унікальний ідентифікатор
az7ar

32

ВПЕВНЕНО: Просто,

Це те, що вам потрібно:

io.to(socket.id).emit("event", data);

кожного разу, коли користувач приєднується до сервера, генеруються деталі сокета, включаючи ідентифікатор. Цей ідентифікатор дійсно допомагає надіслати повідомлення певним людям.

спочатку нам потрібно зберегти всі socket.ids в масиві,

var people={};

people[name] =  socket.id;

тут ім'я - це назва приймача. Приклад:

people["ccccc"]=2387423cjhgfwerwer23;

Отже, тепер ми можемо отримати цей socket.id з іменем одержувача щоразу, коли ми надсилаємо повідомлення:

для цього нам потрібно знати ім'я приймача. Вам потрібно надіслати ім'я приймача на сервер.

остання річ:

 socket.on('chat message', function(data){
io.to(people[data.receiver]).emit('chat message', data.msg);
});

Сподіваюся, це добре працює для вас.

Щасти!!


Чи можете ви створити код на стороні клієнта та сервера.? Я новачок у програмуванні scoket. hmahajan.dmi@gmail.com
Харіш Махаджан

@HARISH, зверніться до посилання нижче, пояснює, що насправді відбувається з боку клієнта .. сподіваюся, це допоможе вам більше .. socket.io/get-started/chat
Trojan

2
Але що, якщо користувач спілкується в чаті одночасно з двома іншими. Чи повідомлення обох користувачів не надходитиме в обидва вікна?
Шаран Мохандас,

Якщо користувачів більше двох, це не спрацює правильно
Мохамад Хашам,

кожного разу, коли користувачі підключають зміни ідентифікатора сокета, тому у випадку, якщо користувач відкриє ваш додаток на декількох вкладках, він отримає відповідь на той, який ви зберегли та надіслали іншим з'єднанням сокета
Vikas Kandari,

8

Ви можете звернутися до номерів socket.io . Коли ви стискаєте сокет - ви можете приєднати його до іменованої кімнати, наприклад "user. # {Userid}".

Після цього ви можете надіслати приватне повідомлення будь-якому клієнту під зручним іменем, наприклад:

io.sockets.in ('user.125'). emit ('new_message', {text: "Hello world"})

Операцією вище ми надсилаємо "new_message" користувачеві "125".

Дякую.


Привіт, товаришу, дякую за першу відповідь, я спробую це повідомити про це, тому що я не хочу створювати чат, а приватний месенджер, як ти можеш використовувати у мережі Facebook.
Нізар Б.

Хтось може мені допомогти у цій справі, я справді застряг, я хотів би додати ім’я користувача, пов’язане з моїм сокетом, і дозволити моїй програмі надсилати повідомлення конкретному користувачеві, без чату, це месенджер Facebook. Дякую, якщо знаєте!
Нізар Б.

Спочатку ви повинні розуміти, що це ім’я користувача має бути унікальним для всіх користувачів. І другий - чи не забули ви підписатися на випущені повідомлення на стороні клієнта?
Володимир Курійов

Проблема цього полягає в тому, що ви втрачаєте можливість використовувати зворотні дзвінки, оскільки вони заборонені в ефірі, що ви насправді робите тут, трансляцію до його приватної кімнати.
bluehallu

@VladimirKurijov, пан Катча не хоче користуватися кімнатами, і я згоден, що це не рішення його проблеми.
miksiii

4

У проекті нашої компанії ми використовуємо підхід "кімнати", і його назва - це поєднання ідентифікаторів користувачів усіх користувачів у розмові як унікальний ідентифікатор (наша реалізація більше нагадує месенджер facebook), приклад:

| ідентифікатор | назва | 1 | Скотт | 2 | Сьюзен

ім'я "кімната" буде "1-2" (ідентифікатори впорядковуються за вибором), а при відключенні socket.io автоматично прибирає кімнату

таким чином ви надсилаєте повідомлення просто в цю кімнату і лише для користувачів Інтернету (підключених) (менше пакетів надсилається по всьому серверу).


1

Дозвольте мені зробити це простішим із кімнатами socket.io. подати запит на приєднання до сервера сервера з унікальним ідентифікатором. тут ми використовуємо електронний лист як унікальний ідентифікатор.

Клієнтська розетка.io

socket.on('connect', function () {
  socket.emit('join', {email: user@example.com});
});

Коли користувач приєднався до сервера, створіть кімнату для цього користувача

Серверний сокет.io

io.on('connection', function (socket) {
   socket.on('join', function (data) {    
    socket.join(data.email);
  });
});

Тепер ми готові приєднатися. нехай випромінює щось із серверної toкімнати, щоб користувач міг слухати.

Серверний сокет.io

io.to('user@example.com').emit('message', {msg: 'hello world.'});

Дозвольте завершити тему прослуховуванням messageподії на стороні клієнта

socket.on("message", function(data) {
  alert(data.msg);
});

Довідка з номерів Socket.io

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.