Jak wysłać wiadomość do konkretnego klienta za pomocą socket.io


96

Zaczynam od socket.io + node.js, wiem, jak wysłać wiadomość lokalnie i nadać socket.broadcast.emit() funkcję: - wszyscy podłączeni klienci otrzymują tę samą wiadomość.

Teraz chciałbym wiedzieć, jak wysłać prywatną wiadomość do konkretnego klienta, mam na myśli jedno gniazdo do prywatnej rozmowy między 2 osobami (strumień klient-klient). Dzięki.


Przepraszam psiphi75, ale ten link nie odpowiada na moją odpowiedź, nie jest powtórzeniem pytania.
Nizar B.

1
@ psiphi75, to nie jest duplikat
softvar

1
Nie znoszę ludzi takich jak @psiphi. Czy jesteś w ogóle programistą? W jaki sposób pytanie dotyczące HTML5 odnosi się do samodzielnej biblioteki? I bez względu na to, co jest warte, WebSockets NIE są Socket.io. Socket.io to biblioteka, która może używać WebSockets, ale ja dygresję. Jest to również bardziej szczegółowe pytanie dotyczące biblioteki, dotyczące wysyłania danych tylko do konkretnych klientów, a nie samej technologii.
Levi Roberts,


@ bugwheels94 Nie bardzo, ten post pochodzi z 2011 roku i ponieważ nodejs miał mnóstwo zmian w kodzie. ten post jest zdecydowanie ważnym pytaniem / odpowiedzią na ten problem.
Nizar B.

Odpowiedzi:


102

Kiedy użytkownik łączy się, powinien wysłać do serwera wiadomość z nazwą użytkownika, która musi być unikalna, np. E-mail.

Para nazwa użytkownika i gniazdo powinny być przechowywane w obiekcie takim jak ten:

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

Na kliencie wyemituj obiekt do serwera z następującymi danymi:

{
    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]
}

Nasłuchuj wiadomości na serwerze. Po odebraniu wiadomości wyemituj dane do odbiorcy.

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

Na kliencie nasłuchuj emisji z serwera o nazwie „ReceivedMessage”, a odczytując dane, możesz obsłużyć, od kogo pochodzą i jaka wiadomość została wysłana.


27
Jeśli korzystasz z tego rozwiązania, musisz zrozumieć: 1. Kiedy użytkownik się rozłączy, musisz wyczyścić obiekt „użytkowników” 2. Nie obsługuje drugiego połączenia - na przykład z innej przeglądarki. Więc jeśli użytkownik łączy się z innej przeglądarki - stare połączenie zostanie nadpisane.
Vladimir Kurijov

1
jak można przechowywać obiekt gniazda w magazynie danych? Zakładam, że to nie działa, jeśli masz więcej niż jeden proces węzłowy.
chovy


11
Proponuję nie korzystać z tego rozwiązania. Skończyło się na tym, że straciłem dużo czasu, próbując pokonać ograniczenia tego podejścia. Zobacz rozwiązanie @ az7ar i to wyjaśnienie, dlaczego jest lepsze .
Daniel Que

@DanielQue +1. O wiele lepiej niż natywna funkcjonalność. Dzięki!
Aaron Lelevier

277

Możesz korzystać z pokoi socket.io. Ze strony klienta wyemituj zdarzenie (w tym przypadku "dołączenie" może być dowolne) z dowolnym unikalnym identyfikatorem (email, id).

Strona klienta:

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

Teraz po stronie serwera użyj tych informacji, aby utworzyć unikalne pomieszczenie dla tego użytkownika

Po stronie serwera:

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
  });
});

Tak więc teraz każdy użytkownik dołączył do pokoju nazwanego na podstawie adresu e-mail użytkownika. Więc jeśli chcesz wysłać konkretnemu użytkownikowi wiadomość, po prostu musisz

Po stronie serwera:

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

Ostatnią rzeczą do zrobienia po stronie klienta jest odsłuchanie zdarzenia „new_msg”.

Strona klienta:

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

Mam nadzieję, że wpadłeś na pomysł.


3
zmień tę linię io.socket.in ('user1@example.com '). emit (' new_msg ', {msg:' hello '}); na przykład io.sockets.in ('user1@example.com '). emit (' new_msg ', {msg:' hello '});
silvesterprabu

42
Ta odpowiedź jest znacznie lepsza niż obecnie akceptowana odpowiedź. Oto dlaczego: 1) Nie musisz zarządzać globalną tablicą klientów i czyścić ją. 2) Działa nawet wtedy, gdy użytkownik ma otwartych wiele kart na tej samej stronie. 3) Można go łatwo rozszerzyć do pracy z klastrem węzłów (wieloma procesami) z socket.io-redis.
Daniel Que

2
jak zrobić {email: user1@example.com}różne dla wszystkich połączeń, czy wszyscy klienci, którzy przechodzą do aplikacji, nie mają użytkownika, user1@example.comjak ustawić go jako użytkownika user2@example.comdla drugiego klienta, który się łączy, abym mógł mieć różne pokoje. przepraszam, jeśli to irytujące pytanie.
puste gniazdo jack

2
pokochałem to rozwiązanie, ale uważam, że bezpieczeństwo jest tutaj zagrożone. Co jeśli zmienię e-mail w skrypcie po stronie klienta. Teraz mogę czytać także inne prywatne wiadomości. Co ty mówisz?
Gopinath Shiva

3
to nie musi być e-mail
Podałem

32

PEWNOŚĆ: Po prostu,

Oto, czego potrzebujesz:

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

Za każdym razem, gdy użytkownik dołączył do serwera, zostaną wygenerowane szczegóły gniazda, w tym identyfikator. To identyfikator naprawdę pomaga wysłać wiadomość do określonych osób.

najpierw musimy przechowywać wszystkie socket.ids w tablicy,

var people={};

people[name] =  socket.id;

tutaj nazwa to nazwa odbiorcy. Przykład:

people["ccccc"]=2387423cjhgfwerwer23;

Więc teraz możemy pobrać ten socket.id z nazwą odbiorcy za każdym razem, gdy wysyłamy wiadomość:

w tym celu musimy znać nazwę odbiorcy. Musisz wyemitować nazwę odbiorcy do serwera.

ostatnia rzecz to:

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

Mam nadzieję, że to działa dobrze dla Ciebie.

Powodzenia!!


Czy możesz utworzyć kod po stronie klienta i po stronie serwera.? Jestem nowy w programowaniu scoket. hmahajan.dmi@gmail.com
Harish Mahajan

@HARISH, zapoznaj się z poniższym linkiem, wyjaśnia, co naprawdę dzieje się po stronie klienta. Mam nadzieję, że to pomoże ci bardziej .. socket.io/get-started/chat
Trojan

2
Ale co, jeśli użytkownik rozmawia jednocześnie z 2 innymi osobami. Czy wiadomość od obu użytkowników nie pojawi się w obu oknach?
Sharan Mohandas

Jeśli jest więcej niż dwóch użytkowników, to nie zadziała
Mohhamad Hasham

za każdym razem, gdy użytkownik łączy się z gniazdem, zmienia się identyfikator gniazda, więc jeśli użytkownik otworzy aplikację na wielu kartach, otrzyma odpowiedź na jedną, którą zapisałeś i wysłałeś do innych połączeń gniazd
Vikas Kandari

8

Możesz odnieść się do pokoi socket.io . Kiedy podałeś gniazdo - możesz dołączyć go do nazwanego pokoju, na przykład „user. # {Userid}”.

Następnie możesz wysłać prywatną wiadomość do dowolnego klienta pod dogodną nazwą, na przykład:

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

W powyższej operacji wysyłamy „new_message” do użytkownika „125”.

dzięki.


Cześć kolego, dziękuję za pierwszą odpowiedź, spróbuję i dam Ci znać, ponieważ nie chcę budować czatu, ale prywatnego komunikatora, takiego jak możesz używać w sieci Facebook.
Nizar B.

Czy ktoś może mi pomóc w tej sprawie, naprawdę utknąłem, chciałbym dodać nazwę użytkownika połączoną z moim gniazdem i pozwolić mojej aplikacji na wysyłanie wiadomości do określonego użytkownika, bez czatu, to Facebook jak komunikator. Dzięki, jeśli wiesz!
Nizar B.,

Najpierw musisz zrozumieć, że ta nazwa użytkownika musi być unikalna dla wszystkich użytkowników. A druga - czy nie zapomniałeś zapisać się na wysyłaną wiadomość po stronie klienta?
Vladimir Kurijov 08.07.13

Problem polega na tym, że tracisz możliwość używania callbacków, ponieważ nie są one dozwolone w transmisjach, co tak naprawdę robisz tutaj, transmisja do jego prywatnego pokoju.
bluehallu

@VladimirKurijov, pan Katcha nie chce korzystać z pokoi i zgadzam się, że to nie jest rozwiązanie jego problemu.
miksiii

4

W projekcie naszej firmy stosujemy podejście „pokoje”, a jego nazwa jest połączeniem identyfikatorów wszystkich użytkowników w rozmowie jako unikalnego identyfikatora (nasza implementacja bardziej przypomina komunikator facebookowy), przykład:

| id | nazwa | 1 | Scott | 2 | Susan

Nazwa „pokoju” będzie brzmiała „1-2” (identyfikatory są uporządkowane rosnąco) i po odłączeniu socket.io automatycznie czyści pomieszczenie

w ten sposób wysyłasz wiadomości tylko do tego pokoju i tylko do użytkowników online (połączonych) (mniej pakietów wysyłanych przez serwer).


1

Pozwól, że uproszczę to dzięki pokojom socket.io. zażądaj serwera z unikalnym identyfikatorem, aby dołączyć do serwera. tutaj używamy adresu e-mail jako unikalnego identyfikatora.

Klient Socket.io

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

Gdy użytkownik dołączył do serwera, utwórz pokój dla tego użytkownika

Serwer Socket.io

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

Teraz wszyscy jesteśmy gotowi do przyłączenia się. niech wyemituje coś z serwerowni to, aby użytkownik mógł słuchać.

Serwer Socket.io

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

Sfinalizujmy temat wysłuchaniem messagezdarzenia po stronie klienta

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

Odniesienie z pokoi Socket.io

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.