Як надіслати повідомлення певному клієнту за допомогою 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.