So senden Sie mit socket.io eine Nachricht an einen bestimmten Client

95

Ich beginne mit socket.io + node.js und weiß, wie man eine Nachricht lokal sendet und wie man eine socket.broadcast.emit()Funktion sendet : - Alle verbundenen Clients erhalten dieselbe Nachricht.

Jetzt möchte ich wissen, wie man eine private Nachricht an einen bestimmten Client sendet. Ich meine einen Socket für einen privaten Chat zwischen zwei Personen (Client-zu-Client-Stream). Vielen Dank.

Nizar B.
quelle
Sorry psiphi75, aber dieser Link antwortet nicht auf meine Antwort, ist keine doppelte Frage.
Nizar B.
1
@ psiphi75, es ist kein Duplikat
softvar
1
Ich kann Leute wie @psiphi nicht leiden. Bist du überhaupt ein Entwickler? In welcher Beziehung steht eine HTML5-spezifische Frage zu einer eigenständigen Bibliothek? Und für das, was es wert ist, sind WebSockets NICHT Socket.io. Socket.io ist eine Bibliothek, die WebSockets verwenden kann, aber ich schweife ab. Dies ist auch eine spezifischere Frage in Bezug auf die Bibliothek zum Senden von Daten nur an bestimmte Clients, nicht zur Technologie selbst.
Levi Roberts
@ bugwheels94 Nicht wirklich, dieser Beitrag stammt aus dem Jahr 2011 und da nodejs viele Änderungen in Bezug auf den Code hatte. Dieser Beitrag ist definitiv eine gültige Frage / Antwort für dieses Problem.
Nizar B.

Antworten:

101

Wenn ein Benutzer eine Verbindung herstellt, sollte er eine Nachricht mit einem Benutzernamen an den Server senden, der eindeutig sein muss, z. B. eine E-Mail.

Ein Paar aus Benutzername und Socket sollte in einem Objekt wie dem folgenden gespeichert werden:

var users = {
    '[email protected]': [socket object],
    '[email protected]': [socket object],
    '[email protected]': [socket object]
}

Senden Sie auf dem Client ein Objekt mit den folgenden Daten an den Server:

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

Warten Sie auf dem Server auf Nachrichten. Wenn eine Nachricht empfangen wird, senden Sie die Daten an den Empfänger.

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

Warten Sie auf dem Client auf Emits vom Server mit dem Namen "receiveMessage". Durch Lesen der Daten können Sie festlegen, von wem sie stammen und welche Nachricht gesendet wurde.

Adam
quelle
26
Wenn Sie diese Lösung verwenden, müssen Sie Folgendes verstehen: 1. Wenn der Benutzer die Verbindung trennt, müssen Sie das Objekt 'Benutzer' bereinigen. 2. Die zweite Verbindung wird nicht unterstützt - beispielsweise von einem anderen Browser. Wenn der Benutzer eine Verbindung über einen anderen Browser herstellt, wird die alte Verbindung überschrieben.
Vladimir Kurijov
1
Wie würden Sie das Socket-Objekt in einem Datenspeicher speichern? Ich gehe davon aus, dass dies nicht funktioniert, wenn Sie mehr als einen Knotenprozess haben.
Chovy
@chovy du musst redis benutzen. Überprüfen Sie diese github.com/LearnBoost/Socket.IO/wiki/Configuring-Socket.IO
Vladimir Kurijov
11
Ich würde vorschlagen, diese Lösung nicht zu verwenden. Am Ende habe ich viel Zeit damit verschwendet, die Grenzen dieses Ansatzes zu überwinden. Siehe @ az7ars Lösung und diese Erklärung, warum es besser ist .
Daniel Que
@ DanielQue +1. Viel besser, um native Funktionalität zu nutzen. Vielen Dank!
Aaron Lelevier
272

Sie können socket.io Räume verwenden. Auf der Clientseite wird ein Ereignis (in diesem Fall "Beitritt" kann alles sein) mit einer eindeutigen Kennung (E-Mail, ID) ausgegeben.

Kundenseite:

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

Verwenden Sie diese Informationen nun von der Serverseite aus, um einen eindeutigen Raum für diesen Benutzer zu erstellen

Serverseite:

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

Jetzt ist jeder Benutzer einem Raum beigetreten, der nach der E-Mail-Adresse des Benutzers benannt ist. Wenn Sie also einem bestimmten Benutzer eine Nachricht senden möchten, müssen Sie dies nur tun

Serverseite:

io.sockets.in('[email protected]').emit('new_msg', {msg: 'hello'});

Das Letzte, was auf der Clientseite noch zu tun ist, ist das Abhören des Ereignisses "new_msg".

Kundenseite:

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

Ich hoffe du kommst auf die Idee.

az7ar
quelle
2
Bitte ändern Sie diese Zeile io.socket.in ('[email protected] '). emit (' new_msg ', {msg:' hello '}); wie folgt io.sockets.in ('[email protected] '). emit (' new_msg ', {msg:' hello '});
Silvesterprabu
42
Diese Antwort ist viel besser als die derzeit akzeptierte Antwort. Hier ist der Grund: 1) Sie müssen das globale Array von Clients nicht verwalten und bereinigen. 2) Es funktioniert auch, wenn ein Benutzer mehrere Registerkarten auf derselben Seite geöffnet hat. 3) Es kann leicht erweitert werden, um mit einem Knotencluster (mehrere Prozesse) mit zu arbeiten socket.io-redis.
Daniel Que
2
Wie unterscheidet man sich {email: [email protected]}für alle Verbindungen? Nicht alle Clients, die zur App gehen, haben Benutzer. [email protected]Wie würde ich sie [email protected]für den zweiten Client, der eine Verbindung herstellt, zum Benutzer machen , damit ich unterschiedliche Räume haben kann? Entschuldigung, wenn dies eine nervige Frage ist.
Jack Blank
2
Ich habe die Lösung geliebt, aber ich glaube, dass die Sicherheit hier gefährdet ist. Was ist, wenn ich die E-Mail im Skript auf der Clientseite ändere? Jetzt kann ich auch andere private Nachrichten lesen. Was sagst du?
Gopinath Shiva
3
Es muss keine E-Mail sein. Ich erwähnte eine eindeutige Kennung
Az7ar
32

SICHER: Einfach,

Das brauchen Sie:

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

Wenn ein Benutzer dem Server beitritt, werden Socket-Details einschließlich der ID generiert. Dies ist die ID, die wirklich hilft, eine Nachricht an bestimmte Personen zu senden.

Zuerst müssen wir alle socket.ids im Array speichern.

var people={};

people[name] =  socket.id;

Hier ist der Name des Empfängers. Beispiel:

people["ccccc"]=2387423cjhgfwerwer23;

Jetzt können wir diese socket.id mit dem Empfängernamen abrufen, wenn wir eine Nachricht senden:

Dazu müssen wir den Empfängernamen kennen. Sie müssen den Empfängernamen an den Server senden.

Das Letzte ist:

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

Hoffe das funktioniert gut für dich.

Viel Glück!!

Trojaner
quelle
Können Sie einen clientseitigen und serverseitigen Code erstellen? Ich bin neu in der Scoket-Programmierung. [email protected]
Harish Mahajan
@ Harish, siehe Link unten, erklärt, was wirklich von Client-Seite passiert .. Ich
Trojaner
2
Was aber, wenn der Benutzer gleichzeitig mit zwei anderen Personen chattet? Wird die Nachricht von beiden Benutzern nicht in beiden Fenstern angezeigt?
Sharan Mohandas
Wenn es mehr als zwei Benutzer gibt, wird es nicht richtig funktionieren
Mohhamad Hasham
Jedes Mal, wenn Benutzer eine Verbindung zu einer Änderung der Socket-ID herstellen, erhält der Benutzer, falls er Ihre App in mehreren Registerkarten öffnet, eine Antwort auf eine App, die Sie gespeichert und an andere Socket-Verbindungen gesendet haben
Vikas Kandari,
8

Sie können sich auf socket.io Räume beziehen . Wenn Sie die Steckdose mit der Hand schütteln, können Sie ihn in einen benannten Raum einbinden, zum Beispiel "Benutzer. # {Benutzer-ID}".

Danach können Sie eine private Nachricht unter einem geeigneten Namen an einen beliebigen Client senden, zum Beispiel:

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

Im obigen Vorgang senden wir "new_message" an den Benutzer "125".

Vielen Dank.

Vladimir Kurijov
quelle
Hallo Kumpel, danke für deine erste Antwort, ich werde es versuchen und dich darüber informieren, weil ich keinen Chat erstellen möchte, sondern einen privaten Messenger, wie du ihn im Facebook-Netzwerk verwenden kannst.
Nizar B.
Kann mir jemand in dieser Angelegenheit helfen, ich stecke wirklich fest, ich möchte einen Benutzernamen hinzufügen, der mit meinem Socket verknüpft ist, und meiner Anwendung erlauben, eine Nachricht an einen bestimmten Benutzer zu senden, kein Chatroom, es ist ein Facebook-ähnlicher Messenger. Danke, wenn du es weißt!
Nizar B.
Zuerst muss man verstehen, dass dieser Benutzername für alle Benutzer eindeutig sein muss. Und die zweite - haben Sie nicht vergessen, die gesendete Nachricht auf der Clientseite zu abonnieren?
Vladimir Kurijov
Das Problem dabei ist, dass Sie die Möglichkeit verlieren, Rückrufe zu verwenden, da diese in Sendungen nicht zulässig sind, was Sie hier wirklich tun, eine Sendung in sein Privatzimmer.
Bluehallu
@VladimirKurijov, Herr Katcha möchte keine Zimmer benutzen und ich stimme zu, dass dies nicht die Lösung für sein Problem ist.
Miksiii
4

In einem Projekt unseres Unternehmens verwenden wir den "Räume" -Ansatz. Der Name ist eine Kombination der Benutzer-IDs aller Benutzer in einer Konversation als eindeutige Kennung (unsere Implementierung ähnelt eher dem Facebook Messenger). Beispiel:

| id | Name | 1 | Scott | 2 | Susan

Der Name "Raum" lautet "1-2" (IDs werden als Asc bestellt) und beim Trennen der Steckdose wird der Raum automatisch aufgeräumt

Auf diese Weise senden Sie Nachrichten nur an diesen Raum und nur an (verbundene) Online-Benutzer (weniger Pakete, die über den Server gesendet werden).

Rami
quelle
1

Lassen Sie es mich mit socket.io-Räumen einfacher machen. Fordern Sie einen Server mit einer eindeutigen Kennung an, einem Server beizutreten. Hier verwenden wir eine E-Mail als eindeutige Kennung.

Client Socket.io

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

Wenn der Benutzer einem Server beigetreten ist, erstellen Sie einen Raum für diesen Benutzer

Server Socket.io

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

Jetzt sind wir alle bereit, uns anzuschließen. Lassen Sie etwas vom Server ausgebento , damit der Benutzer zuhören kann.

Server Socket.io

io.to('[email protected]').emit('message', {msg: 'hello world.'});

Lassen Sie das Thema mit dem Abhören des messageEreignisses auf der Clientseite abschließen

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

Die Referenz von Socket.io Zimmern

Lalit Mohan
quelle