Comment envoyer un message à un client particulier avec socket.io

96

Je commence par socket.io + node.js, je sais envoyer un message localement et diffuser une socket.broadcast.emit()fonction: - tous les clients connectés reçoivent le même message.

Maintenant, j'aimerais savoir comment envoyer un message privé à un client particulier, je veux dire une prise pour un chat privé entre 2 personnes (flux client-à-client). Merci.

Nizar B.
la source
Désolé psiphi75 mais ce lien ne répond pas à ma réponse, n'est pas une question en double.
Nizar B.
1
@ psiphi75, ce n'est pas un doublon
softvar
1
Je ne supporte pas les gens comme @psiphi. Êtes-vous même développeur? Quel est le lien entre une question spécifique HTML5 et une bibliothèque autonome? Et pour ce que ça vaut, les WebSockets ne sont PAS Socket.io. Socket.io est une bibliothèque qui peut UTILISER WebSockets, mais je m'éloigne du sujet. Il s'agit également d'une question plus spécifique concernant la bibliothèque concernant l'envoi de données à des clients spécifiques uniquement, et non la technologie elle-même.
Levi Roberts
Double
bugwheels94
@ bugwheels94 Pas vraiment, ce post date de 2011 et depuis que nodejs a eu beaucoup de changements au niveau du code. cet article est définitivement une question / réponse valable pour ce problème.
Nizar B.

Réponses:

102

Lorsqu'un utilisateur se connecte, il doit envoyer un message au serveur avec un nom d'utilisateur qui doit être unique, comme un e-mail.

Une paire de nom d'utilisateur et de socket doit être stockée dans un objet comme celui-ci:

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

Sur le client, émettez un objet vers le serveur avec les données suivantes:

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

Sur le serveur, écoutez les messages. Lorsqu'un message est reçu, émettez les données vers le récepteur.

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

Sur le client, écoutez les émissions du serveur appelé «receiveMessage», et en lisant les données, vous pouvez gérer la provenance et le message envoyé.

Adam
la source
26
Si vous utilisez cette solution, vous devez comprendre: 1. Lorsque l'utilisateur se déconnecte, vous devez nettoyer l'objet «utilisateurs». 2. Il ne prend pas en charge la deuxième connexion - par exemple à partir d'un autre navigateur. Donc, si l'utilisateur se connecte à partir d'un autre navigateur, l'ancienne connexion sera remplacée.
Vladimir Kurijov
1
comment stockeriez-vous l'objet socket dans une banque de données? Je suppose que cela ne fonctionne pas si vous avez plus d'un processus de nœud.
chovy
@chovy vous devez utiliser redis. Vérifiez ce github.com/LearnBoost/Socket.IO/wiki/Configuring-Socket.IO
Vladimir Kurijov
11
Je suggère de ne pas utiliser cette solution. J'ai fini par perdre beaucoup de temps à essayer de surmonter les limites de cette approche. Voir la solution de @ az7ar et cette explication pour savoir pourquoi elle est meilleure .
Daniel Que
@DanielQue +1. Bien mieux utiliser la fonctionnalité native. Merci!
Aaron Lelevier
275

Vous pouvez utiliser des salles socket.io. Du côté client, émettez un événement («rejoindre» dans ce cas, peut être n'importe quoi) avec n'importe quel identifiant unique (email, id).

Côté client:

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

Maintenant, du côté du serveur, utilisez ces informations pour créer une salle unique pour cet utilisateur

Du côté serveur:

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

Ainsi, maintenant, chaque utilisateur a rejoint une salle nommée d'après l'e-mail de l'utilisateur. Donc, si vous souhaitez envoyer un message à un utilisateur spécifique, il vous suffit de

Du côté serveur:

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

La dernière chose à faire côté client est d'écouter l'événement "new_msg".

Côté client:

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

J'espère que vous avez l'idée.

az7ar
la source
3
veuillez changer cette ligne io.socket.in ('[email protected] '). emit (' new_msg ', {msg:' hello '}); comme ceci io.sockets.in ('[email protected] '). emit (' new_msg ', {msg:' hello '});
silvesterprabu
42
Cette réponse est bien meilleure que la réponse actuellement acceptée. Voici pourquoi: 1) Vous n'avez pas besoin de gérer et de nettoyer le tableau global de clients. 2) Cela fonctionne même si un utilisateur a plusieurs onglets ouverts sur la même page. 3) Il peut être facilement étendu pour fonctionner avec un cluster de nœuds (processus multiples) avec socket.io-redis.
Daniel Que
2
Comment pouvez-vous rendre {email: [email protected]}différent pour toute connexion si tous les clients qui vont à l'application n'ont pas d'utilisateur, [email protected]comment pourrais-je en faire un utilisateur [email protected]pour le deuxième client qui se connecte afin que je puisse avoir des chambres différentes. désolé si c'est une question ennuyeuse.
jack blank
2
J'ai adoré la solution, mais je crois que la sécurité est compromise ici. Que faire si je change l'e-mail dans le script côté client. Maintenant, je suis également capable de lire d'autres messages privés. Qu'est-ce que tu dis?
Gopinath Shiva
3
il ne doit pas s'agir d'un e-mail J'ai mentionné un identifiant unique
az7ar
32

SÛR: Simplement,

Voici ce dont vous avez besoin:

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

chaque fois qu'un utilisateur rejoint le serveur, les détails du socket seront générés, y compris l'ID. C'est l'ID qui aide vraiment à envoyer un message à des personnes en particulier.

nous devons d'abord stocker tous les socket.ids dans un tableau,

var people={};

people[name] =  socket.id;

ici nom est le nom du destinataire. Exemple:

people["ccccc"]=2387423cjhgfwerwer23;

Donc, maintenant, nous pouvons obtenir ce socket.id avec le nom du destinataire chaque fois que nous envoyons un message:

pour cela, nous devons connaître le nom de réception. Vous devez émettre le nom du récepteur sur le serveur.

la dernière chose est:

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

J'espère que cela fonctionne bien pour vous.

Bonne chance!!

troyen
la source
Pouvez-vous créer un code côté client et côté serveur.? Je suis nouveau dans la programmation scoket. [email protected]
Harish Mahajan
@HARISH, reportez-vous au lien ci-dessous, explique ce qui se passe réellement du côté client..J'espère que cela vous aidera davantage .. socket.io/get-started/chat
Trojan
2
Mais que se passe-t-il si l'utilisateur discute avec 2 autres personnes en même temps. Le message des deux utilisateurs n'apparaîtra-t-il pas dans les deux fenêtres?
Sharan Mohandas
S'il y a plus de deux utilisateurs, cela ne fonctionnera pas correctement
Mohhamad Hasham
chaque fois que les utilisateurs se connectent, l'ID de socket change, donc si l'utilisateur ouvre votre application dans plusieurs onglets, il recevra une réponse à celui que vous avez stocké et envoyé à d'autres connexions de socket
Vikas Kandari
8

Vous pouvez vous référer aux salles socket.io . Lorsque vous avez établi une connexion, vous pouvez le rejoindre dans la salle nommée, par exemple "user. # {Userid}".

Après cela, vous pouvez envoyer un message privé à n'importe quel client par un nom pratique, par exemple:

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

Dans l'opération ci-dessus, nous envoyons "new_message" à l'utilisateur "125".

Merci.

Vladimir Kurijov
la source
Salut mec, merci pour votre première réponse, je vais l'essayer et vous en informer, car je ne veux pas créer un chat mais un messager privé comme vous pouvez utiliser sur le réseau Facebook.
Nizar B.
Quelqu'un peut-il m'aider dans ce dossier, je suis vraiment coincé, je voudrais ajouter un nom d'utilisateur lié à ma socket et permettre à mon application d'envoyer un message à un utilisateur spécifique, pas de chat room, c'est un Facebook comme messenger. Merci si vous savez!
Nizar B.
Au début, vous devez comprendre que ce nom d'utilisateur doit être unique pour tous les utilisateurs. Et le second - n'avez-vous pas oublié de vous abonner au message émis côté client?
Vladimir Kurijov
Le problème avec cela est que vous perdez la capacité d'utiliser les rappels, car ils ne sont pas autorisés dans les émissions, ce que vous faites vraiment ici, une diffusion dans sa salle privée.
bluehallu
@VladimirKurijov, M. Katcha ne veut pas utiliser Rooms et je suis d'accord que ce n'est pas la solution à son problème.
miksiii
4

Dans un projet de notre entreprise, nous utilisons une approche «salles» et son nom est une combinaison d'identifiants d'utilisateur de tous les utilisateurs dans une conversation en tant qu'identifiant unique (notre implémentation ressemble plus à Facebook Messenger), exemple:

| id | nom | 1 | Scott | 2 | Susan

Le nom de "room" sera "1-2" (les identifiants sont classés par ordre croissant) et sur disconnect socket.io nettoie automatiquement la pièce

de cette façon, vous envoyez des messages uniquement à cette salle et uniquement aux utilisateurs en ligne (connectés) (moins de paquets envoyés sur le serveur).

Rami
la source
1

Permettez-moi de simplifier les choses avec les salles socket.io. demander à un serveur avec un identifiant unique de rejoindre un serveur. ici, nous utilisons un e-mail comme identifiant unique.

Client Socket.io

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

Lorsque l'utilisateur rejoint un serveur, créez une salle pour cet utilisateur

Serveur Socket.io

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

Maintenant, nous sommes tous prêts à nous rejoindre. laissez émettre quelque chose à partir de la tosalle des serveurs , afin que l'utilisateur puisse écouter.

Serveur Socket.io

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

Laisser finaliser le sujet en écoutant l' messageévénement côté client

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

La référence des salles Socket.io

Lalit Mohan
la source