Wyślij wiadomość do konkretnego klienta z socket.io i węzeł.js

Pracuję z socket.io i węzeł.js i do tej pory wydaje się całkiem nieźle, ale nie wiem jak wysłać wiadomość z serwera do konkretnego klienta, coś w tym stylu:

client.send(message, receiverSessionId)

Ale ani .send() Ani .broadcast() metody nie wydają się zaspokajać moich potrzeb.

To, co znalazłem jako możliwe rozwiązanie, to to, że metoda .broadcast() akceptuje jako drugi parametr tablicę identyfikatorów sesji, do których nie wysyła wiadomości, więc mogę przekazać tablicę ze wszystkimi identyfikatorami sesji podłączonymi do tego moment na serwer, z wyjątkiem tego, który chciałbym wysłać wiadomość, ale uważam, że musi być lepsze rozwiązanie.

Jakieś pomysły?
Author: Lucio Paiva, 2011-01-10

11 answers

Cóż, musisz złapać za to Klienta (niespodzianka), możesz albo pójść prostą drogą:

var io = io.listen(server);
io.clients[sessionID].send()

Które mogą się zepsuć, nie wątpię w to, ale zawsze jest możliwość, że io.clients może się zmienić, więc używaj powyższego z ostrożnością

Lub śledzisz klientów samodzielnie, dlatego dodajesz je do własnego obiektu clients w detektorze connection i usuwasz je w detektorze disconnect.

Użyłbym tego drugiego, ponieważ w zależności od aplikacji możesz chcieć miej więcej informacji na temat klientów i tak, więc coś w stylu clients[id] = {conn: clientConnect, data: {...}} może załatwić sprawę.

 82
Author: Ivo Wetzel,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-01-10 14:14:13

Odpowiedź Ivo Wetzela nie wydaje się być aktualna w Socket.io 0.95%

W skrócie musisz teraz zapisać socket.id i użyć io.sockets.socket(savedSocketId).emit(...), Aby wysłać do niego wiadomości.

Tak to działa w clustered Node.serwer js:

Najpierw musisz ustawić Redis store jako store, aby wiadomości mogły przejść przez procesy:

var express = require("express");
var redis = require("redis");
var sio = require("socket.io");

var client = redis.createClient()
var app = express.createServer();
var io = sio.listen(app);

io.set("store", new sio.RedisStore);


// In this example we have one master client socket 
// that receives messages from others.

io.sockets.on('connection', function(socket) {

  // Promote this socket as master
  socket.on("I'm the master", function() {

    // Save the socket id to Redis so that all processes can access it.
    client.set("mastersocket", socket.id, function(err) {
      if (err) throw err;
      console.log("Master socket is now" + socket.id);
    });
  });

  socket.on("message to master", function(msg) {

    // Fetch the socket id from Redis
    client.get("mastersocket", function(err, socketId) {
      if (err) throw err;
      io.sockets.socket(socketId).emit(msg);
    });
  });

});

Pominąłem tutaj Kod klastrowy, ponieważ sprawia, że jest to bardziej zaśmiecone, ale to jest trywialne dodać. Wystarczy dodać wszystko do kodu pracownika. Więcej docs here http://nodejs.org/api/cluster.html

 160
Author: Epeli,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-05-09 12:01:40

Każde gniazdo łączy się z pokojem z identyfikatorem gniazda dla nazwy, więc możesz po prostu

io.to(socket#id).emit('hey')

Docs: http://socket.io/docs/rooms-and-namespaces/#default-room

Cheers

 72
Author: Matic Kogovšek,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-12-03 11:28:38

Najprostsze, najbardziej eleganckie rozwiązanie

To tak proste jak:
client.emit("your message");

I to wszystko.

Ale jak? Daj mi przykład

To, czego wszyscy potrzebujemy, to w rzeczywistości pełny przykład,i to jest to, co następuje. Jest to testowane z najnowszymi socket.io Wersja (2.0.3) i jest również przy użyciu nowoczesnego Javascript(który powinniśmy wszyscy używać teraz).

Przykład składa się z dwóch części: serwera i klienta. Ilekroć Klient się połączy, zaczyna odbierać z serwera numer sekwencji okresowej. Dla każdego nowego klienta uruchamiana jest nowa sekwencja, więc serwer musi śledzić je indywidualnie. To jest miejsce, gdzie "muszę wysłać wiadomość do konkretnego klienta" wchodzi w grę. Kod jest bardzo prosty do zrozumienia. Zobaczmy.

Serwer

server.js

const
    io = require("socket.io"),
    server = io.listen(8000);

let
    sequenceNumberByClient = new Map();

// event fired every time a new client connects:
server.on("connection", (socket) => {
    console.info(`Client connected [id=${socket.id}]`);
    // initialize this client's sequence number
    sequenceNumberByClient.set(socket, 1);

    // when socket disconnects, remove it from the list:
    socket.on("disconnect", () => {
        sequenceNumberByClient.delete(socket);
        console.info(`Client gone [id=${socket.id}]`);
    });
});

// sends each client its current sequence number
setInterval(() => {
    for (const [client, sequenceNumber] of sequenceNumberByClient.entries()) {
        client.emit("seq-num", sequenceNumber);
        sequenceNumberByClient.set(client, sequenceNumber + 1);
    }
}, 1000);

Serwer zaczyna nasłuchiwać na porcie 8000 dla połączeń przychodzących. Kiedy ktoś przybywa, dodaje nowego klienta do mapy, aby mógł śledzić jego numer porządkowy. Nasłuchuje również zdarzenia disconnect tego klienta, kiedy usunie je z mapy.

Co sekundę uruchamiany jest timer. Kiedy to zrobi, serwer przechodzi przez mapę i wysyła wiadomość do każdego klienta z jego aktualnym numerem sekwencji. Następnie zwiększa go i zapisuje numer z powrotem na mapie. To wszystko. Bułka z masłem.

Klient

Część klienta jest jeszcze prostsza. Po prostu łączy się z serwerem i słucha seq-num wiadomość, drukując ją na konsoli za każdym razem, gdy przybywa.

client.js

const
    io = require("socket.io-client"),
    ioClient = io.connect("http://localhost:8000");

ioClient.on("seq-num", (msg) => console.info(msg));

Uruchamianie przykładu

Zainstaluj wymagane biblioteki:

npm install socket.io
npm install socket.io-client

Uruchom Serwer:

node server

Otwórz inne okna terminala i odradzaj tylu klientów, ilu chcesz, uruchamiając:

node client

przygotowałem również gist z pełnym kodem tutaj .

 67
Author: Lucio Paiva,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-10-01 15:32:37

W 1.0 należy użyć:

io.sockets.connected[socketid].emit();
 32
Author: PHPthinking,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-02-27 16:37:33

Możesz użyć

//wyślij wiadomość tylko do sender-client

socket.emit('message', 'check this');

/ / lub możesz wysłać do wszystkich słuchaczy, w tym do nadawcy

io.emit('message', 'check this');

//Wyślij do wszystkich słuchaczy z wyjątkiem nadawcy

socket.broadcast.emit('message', 'this is a message');

/ / lub możesz wysłać go do pokoju

socket.broadcast.to('chatroom').emit('message', 'this is the message to all');

 21
Author: DecoderNT,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-06-25 07:25:06

Niezależnie od wersji, której używamy, jeśli tylko konsolujemy.log() obiekt "io", którego używamy w kodzie nodejs po stronie serwera, [np. io.on ('connection', function (socket) {...});], widzimy, że " io " jest tylko obiektem json i istnieje wiele obiektów potomnych, w których przechowywane są Socket id i socket objects.

Używam socket.io Wersja 1.3.5, btw.

Jeśli spojrzymy w obiekt io, zawiera on,

 sockets:
  { name: '/',
    server: [Circular],
    sockets: [ [Object], [Object] ],
    connected:
     { B5AC9w0sYmOGWe4fAAAA: [Object],
       'hWzf97fmU-TIwwzWAAAB': [Object] },

Tutaj możemy zobaczyć skarpety "B5AC9w0sYmOGWe4fAAAA" itp. Więc możemy do,

io.sockets.connected[socketid].emit();

Ponownie, przy dalszej kontroli możemy zobaczyć segmenty takie jak,

 eio:
  { clients:
     { B5AC9w0sYmOGWe4fAAAA: [Object],
       'hWzf97fmU-TIwwzWAAAB': [Object] },

Więc możemy odzyskać Gniazdo, wykonując

io.eio.clients[socketid].emit();

Również, pod silnikiem mamy,

engine:
 { clients:
    { B5AC9w0sYmOGWe4fAAAA: [Object],
      'hWzf97fmU-TIwwzWAAAB': [Object] },

Więc możemy też napisać,

io.engine.clients[socketid].emit();

Więc, myślę, że możemy osiągnąć nasz cel w dowolnym z 3 sposobów wymienionych powyżej,

  1. io.gniazda.podłączony [socketid].emitować(); Lub
  2. io.eio.klientów [socketid].emitować(); Lub
  3. io.silnik.klientów [socketid].emit ();
 12
Author: Suman Barick,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-06-17 10:30:10

Możesz to zrobić

Na serwerze.

global.io=require("socket.io")(server);

io.on("connection",function(client){
    console.log("client is ",client.id);
    //This is handle by current connected client 
    client.emit('messages',{hello:'world'})
    //This is handle by every client
    io.sockets.emit("data",{data:"This is handle by every client"})
    app1.saveSession(client.id)

    client.on("disconnect",function(){
        app1.deleteSession(client.id)
        console.log("client disconnected",client.id);
    })

})

    //And this is handle by particular client 
    var socketId=req.query.id
    if(io.sockets.connected[socketId]!=null) {
        io.sockets.connected[socketId].emit('particular User', {data: "Event response by particular user "});
    }

I na kliencie, jest bardzo łatwy w obsłudze.

var socket=io.connect("http://localhost:8080/")
    socket.on("messages",function(data){
        console.log("message is ",data);
        //alert(data)
    })
    socket.on("data",function(data){
        console.log("data is ",data);
        //alert(data)
    })

    socket.on("particular User",function(data){
        console.log("data from server ",data);
        //alert(data)
    })
 10
Author: abhaygarg12493,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-06-07 12:28:27

Począwszy od wersji 1.4.5, upewnij się, że podajesz poprawnie poprzedzony socketId w io.to (). Brałem socketId, który klient zalogował się do debugowania i był bez prefiksu, więc skończyło się na szukaniu w nieskończoność, aż się dowiedziałem! Możesz więc zrobić to w ten sposób, jeśli identyfikator, który posiadasz, nie jest poprzedzony prefiksem:

io.to('/#' + socketId).emit('myevent', {foo: 'bar'});
 5
Author: risuch,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-07-22 11:23:47

Io. sockets. sockets[socket.id]. emit(...) działało u mnie w v0. 9

 4
Author: aljosa,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-02-01 12:09:02

Socket.IO pozwala na "Przestrzeń nazw" gniazd, co zasadniczo oznacza przypisywanie różnych punktów końcowych lub ścieżek.

To może pomóc: http://socket.io/docs/rooms-and-namespaces/

 0
Author: Igor T.,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-01-12 16:18:42