Оновити всіх клієнтів за допомогою Socket.io?


80

Чи можна змусити всіх клієнтів оновлюватись за допомогою socket.io? Я спробував наступне, але, схоже, це не оновлює інших клієнтів, коли підключається новий клієнт:

JavaScript на сервері:

Я намагаюся надіслати повідомлення всім клієнтам, яке містить поточну кількість підключених користувачів, воно правильно надсилає кількість користувачів .... однак сам клієнт, здається, не оновлюється, поки сторінку не оновлено. Я хочу, щоб це сталося в реальному часі.

var clients = 0;
io.sockets.on('connection', function (socket) {
  ++clients;
  socket.emit('users_count', clients);    
  socket.on('disconnect', function () {
    --clients;
  });
});

Клієнтський JavaScript:

var socket = io.connect('http://localhost');

socket.on('connect', function(){
  socket.on('users_count', function(data){
    $('#client_count').text(data);
    console.log("Connection");
  });
});

Відповіді:


193

Це насправді взагалі не надсилає оновлення іншим клієнтам, натомість просто передає клієнту, який щойно підключився (саме тому ви бачите оновлення при першому завантаженні)

// socket is the *current* socket of the client that just connected
socket.emit('users_count', clients); 

Натомість ви хочете випромінювати всі розетки

io.sockets.emit('users_count', clients);

Крім того, ви можете використовувати функцію трансляції, яка надсилає повідомлення всім, крім сокета, який його запускає:

socket.broadcast.emit('users_count', clients);

1
дякую, чи є щось інше між використанням трансляції та використанням io.sockets.emit?
Джек

4
@Jack Згідно з документацією, "Трансляція означає надсилання повідомлення всім іншим, крім сокета, який його запускає.", Де - як я очікував, інший надішле його всім.
Matt

1
Здається, я зробив помилку, виправивши цю відповідь як редагування. Оскільки редагування було відхилено, знову йдеться: socket.broadcast.emit та io.sockets.emit не є альтернативами один одному в тому сенсі, що вони мають велику різницю. Варіант трансляції випромінює всі сокети, за винятком тригерного сокета, тоді як метод io.sockets справді випромінює всі сокети.
Тіаго Еспінья

Чи може io.sockets.emitбути використано поза сферою дії io.sockets.on('connection', function (s){...?
vsync

2
@Matt з останньою версією API Socket.IO, io.sockets.emit не працює, замість цього використовуйте io.emit.
Gianluca Casati

13

Я виявив, що використання socket.broadcast.emit () буде транслювати лише поточне "з'єднання", але io.sockets.emit транслюватиме всіх клієнтів. тут сервер прослуховує "два з'єднання", що є точно 2 просторами імен сокета

io.of('/namespace').on('connection', function(){
    socket.broadcast.emit("hello");
});
io.of('/other namespace').on('connection',function(){/*...*/});

я намагався використовувати io.sockets.emit () в одному просторі імен, але його отримав клієнт в іншому просторі імен. проте socket.broadcast.emit () просто транслюватиме поточний простір імен сокета.


3

З версії socket.io 0.9 "emit" для мене більше не працював, і я використовую "send"

Ось що я роблю:

Сторона сервера :

var num_of_clients = io.sockets.clients().length;
io.sockets.send(num_of_clients);

Сторона клієнта:

ws = io.connect...
ws.on('message', function(data)
{
var sampleAttributes = fullData.split(',');
if (sampleAttributes[0]=="NumberOfClients")
        {
            console.log("number of connected clients = "+sampleAttributes[1]);
        }
});

1
Тоді ви, мабуть, робите щось не так ... Поточний стан документів "випромінює" socket.io/docs
Адам

0

Ви можете слідувати цьому прикладу для реалізації вашого сценарію.

Ви можете дозволити всім клієнтам приєднатися до загальної кімнати для надсилання деяких оновлень. Кожна розетка може приєднатися до кімнати так:

currentSocket.join("client-presence") //can be any name for room

Тоді ви можете мати клієнтський ключ у своїх сокетах, який містить кілька даних клієнта (ідентифікатор та статус), і якщо статус одного клієнта змінюється, ви можете отримати подію зміни в сокеті так:

socket.on('STATUS_CHANGE',emitClientsPresence(io,namespace,currentSocket); //event name should be same on client & server side for catching and emiting

і тепер ви хочете, щоб усі інші клієнти отримували оновлення, тому ви можете зробити щось подібне:

emitClientsPresence => (io,namespace,currentSocket) {
  io.of(namespace)
        .to(client-presence)
        .emit('STATUS_CHANGE', { id: "client 1", status: "changed status" });
}

Це призведе до події STATUS_CHANGE для всіх сокетів, які приєдналися до кімнати "клієнт-присутність", і тоді ви зможете зафіксувати ту саму подію на стороні клієнта та оновити статус іншого клієнта.


0

Відповідно до цього мовлення . З сервером nodejs ви можете використовувати це:

io.emit('event_id', {your_property: 'your_property_field'});

Обов’язково ініціалізуйте веб-сокет, наприклад:

var express = require('express');
var http = require('http');
var app = express();
var server = http.Server(app);
var io = require('socket.io')(server);

app.get('/', function (req, res) {
    res.send('Hello World!');
    io.emit('event_hello', {message: 'Hello Socket'});
});

server.listen(3000, function () {
  console.log('Example app listening on port 3000!');
});

У цьому випадку, коли користувач досягне вашого сервера, буде передано "event_hello" для всіх клієнтів веб-сокетів із об'єктом json {повідомлення: 'Hello Socket'}.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.