Come inviare un messaggio a un particolare client con socket.io


96

Comincio con socket.io + node.js, so come inviare un messaggio in locale e come trasmettere la socket.broadcast.emit()funzione: - tutti i client collegati ricevono lo stesso messaggio.

Ora, vorrei sapere come inviare un messaggio privato a un particolare client, intendo un socket per una chat privata tra 2 persone (flusso client-to-client). Grazie.


Spiacente psiphi75 ma questo link non risponde alla mia risposta, non è una domanda duplicata.
Nizar B.

1
@ psiphi75, non è assolutamente un duplicato
softvar

1
Non sopporto persone come @psiphi. Sei anche uno sviluppatore? In che modo una domanda specifica HTML5 è correlata a una libreria autonoma? E per quello che vale, i WebSocket NON sono Socket.io. Socket.io è una libreria che può UTILIZZARE WebSocket, ma sto divagando. Questa è anche una domanda più specifica relativa alla libreria sull'invio di dati solo a client specifici, non sulla tecnologia stessa.
Levi Roberts


@ bugwheels94 Non proprio, questo post è del 2011 e poiché nodejs ha avuto un sacco di modifiche dal punto di vista del codice. questo post è sicuramente una domanda / risposta valida per questo problema.
Nizar B.

Risposte:


102

Quando un utente si connette, dovrebbe inviare un messaggio al server con un nome utente che deve essere univoco, come un'e-mail.

Una coppia di nome utente e socket dovrebbe essere archiviata in un oggetto come questo:

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

Sul client, invia un oggetto al server con i seguenti dati:

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

Sul server, ascolta i messaggi. Quando viene ricevuto un messaggio, invia i dati al destinatario.

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

Sul client, ascolta gli emittenti dal server chiamati "ricevutiMessaggio" e leggendo i dati puoi gestire da chi provengono e il messaggio che è stato inviato.


26
Se si utilizza questa soluzione, è necessario comprendere: 1. Quando l'utente si disconnette, è necessario ripulire l'oggetto "utenti" 2. Non supporta la seconda connessione, ad esempio da un altro browser. Quindi, se l'utente si connette da un altro browser, la vecchia connessione verrà ignorata.
Vladimir Kurijov

1
come archiviereste l'oggetto socket in un datastore? Presumo che questo non funzioni se hai più di un processo di nodo.
chovy


11
Suggerirei di non utilizzare questa soluzione. Ho finito per perdere molto tempo cercando di superare i limiti di questo approccio. Vedi la soluzione di @az7ar e questa spiegazione del motivo per cui è migliore .
Daniel Que

@DanielQue +1. Molto meglio utilizzare le funzionalità native. Grazie!
Aaron Lelevier

275

Puoi usare socket.io rooms. Dal lato client emette un evento ("join" in questo caso, può essere qualsiasi cosa) con qualsiasi identificatore univoco (email, id).

Dalla parte del cliente:

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

Ora, dal lato server, usa queste informazioni per creare una stanza unica per quell'utente

Lato server:

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

Quindi, ora ogni utente si è unito a una stanza denominata in base all'e-mail dell'utente. Quindi, se vuoi inviare un messaggio a un utente specifico, devi solo farlo

Lato server:

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

L'ultima cosa che resta da fare sul lato client è ascoltare l'evento "new_msg".

Dalla parte del cliente:

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

Spero che tu abbia avuto l'idea.


3
per favore cambia questa riga io.socket.in ('user1@example.com '). emit (' new_msg ', {msg:' hello '}); come questo io.sockets.in ('user1@example.com '). emit (' new_msg ', {msg:' hello '});
silvesterprabu

42
Questa risposta è molto migliore della risposta attualmente accettata. Ecco perché: 1) Non è necessario gestire e ripulire la gamma globale di client. 2) Funziona anche se un utente ha più schede aperte sulla stessa pagina. 3) Può essere facilmente esteso per lavorare con un cluster di nodi (più processi) con socket.io-redis.
Daniel Que

2
come si fa a rendere {email: user1@example.com}diverso per tutte le connessioni non tutti i client che accedono all'app hanno un utente user1@example.comcome lo renderò utente user2@example.comper il secondo client che si connette in modo da poter avere stanze diverse. scusa se questa è una domanda fastidiosa.
jack vuoto

2
mi è piaciuta la soluzione, ma credo che la sicurezza sia compromessa qui. Cosa succede se cambio l'email nello script sul lato client. Ora sono in grado di leggere anche altri messaggi privati. Che dici?
Gopinath Shiva

3
non deve essere un'e-mail Ho menzionato alcun identificatore univoco
az7ar

32

SICURO: semplicemente,

Questo è quello di cui hai bisogno :

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

ogni volta che un utente si è unito al server, i dettagli del socket verranno generati incluso l'ID. Questo è l'ID che aiuta davvero a inviare un messaggio a determinate persone.

per prima cosa dobbiamo memorizzare tutti i socket.ids nell'array,

var people={};

people[name] =  socket.id;

qui nome è il nome del destinatario. Esempio:

people["ccccc"]=2387423cjhgfwerwer23;

Quindi, ora possiamo ottenere quel socket.id con il nome del destinatario ogni volta che inviamo un messaggio:

per questo abbiamo bisogno di conoscere il nome del destinatario. È necessario inviare il nome del destinatario al server.

la cosa finale è:

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

Spero che questo funzioni bene per te.

In bocca al lupo!!


Potete creare un codice lato client e lato server.? Sono nuovo nella programmazione di scoket. hmahajan.dmi@gmail.com
Harish Mahajan

@ HARISH, fai riferimento al link sotto, spiega cosa sta realmente accadendo dal lato client .. spero che questo ti aiuti di più .. socket.io/get-started/chat
Trojan

2
Ma cosa succede se l'utente sta chattando con altri 2 contemporaneamente. Il messaggio di entrambi gli utenti non arriverà in entrambe le finestre?
Sharan Mohandas

Se ci sono più di due utenti, non funzionerà correttamente
Mohhamad Hasham

ogni volta che gli utenti connettono le modifiche all'ID del socket, nel caso in cui l'utente apra la tua app in più schede riceverà risposta a una che hai memorizzato e inviato ad altre connessioni socket
Vikas Kandari

8

Puoi fare riferimento a socket.io rooms . Quando hai effettuato l'handshaking del socket, puoi unirti a lui nella stanza denominata, ad esempio "user. # {Userid}".

Dopodiché, puoi inviare un messaggio privato a qualsiasi client con un nome conveniente, ad esempio:

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

Nell'operazione sopra inviamo "new_message" all'utente "125".

Grazie.


Ciao amico, grazie per la tua prima risposta, lo proverò e te lo farò sapere, perché non voglio costruire una chat ma un messenger privato come te puoi usare sulla rete Facebook.
Nizar B.

Qualcuno può aiutarmi in questa faccenda, sono davvero bloccato, vorrei aggiungere un nome utente collegato al mio socket e consentire alla mia applicazione di inviare un messaggio a un utente specifico, nessuna chat room, è un messenger simile a Facebook. Grazie se lo sai!
Nizar B.

All'inizio devi capire che questo nome utente deve essere univoco per tutti gli utenti. E il secondo: non ti sei dimenticato di iscriverti per il messaggio emesso dal lato client?
Vladimir Kurijov

Il problema con questo è che perdi la possibilità di utilizzare i callback, poiché non sono consentiti nelle trasmissioni, che è ciò che stai facendo davvero qui, una trasmissione nella sua stanza privata.
bluehallu

@VladimirKurijov, il signor Katcha non vuole usare Rooms e sono d'accordo che non è la soluzione al suo problema.
miksiii

4

In un progetto della nostra azienda stiamo utilizzando l'approccio "stanze" e il suo nome è una combinazione di ID utente di tutti gli utenti in una conversazione come identificatore univoco (la nostra implementazione è più simile a Facebook Messenger), esempio:

| id | nome | 1 | Scott | 2 | Susan

Il nome della "stanza" sarà "1-2" (gli ID sono ordinati Asc.) e alla disconnessione socket.io pulisce automaticamente la stanza

in questo modo si inviano messaggi solo a quella stanza e solo agli utenti online (connessi) (meno pacchetti inviati attraverso il server).


1

Lascia che sia più semplice con socket.io rooms. richiedere un server con un identificatore univoco per partecipare a un server. qui stiamo usando un'e-mail come identificatore univoco.

Client Socket.io

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

Quando l'utente si è unito a un server, creare una stanza per quell'utente

Server Socket.io

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

Ora siamo tutti pronti per entrare. lascia emettere qualcosa dalla tosala server , in modo che l'utente possa ascoltare.

Server Socket.io

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

Finisci l'argomento ascoltando l' messageevento dal lato client

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

Il riferimento da Socket.io rooms

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.