Оновити всіх клієнтів за допомогою 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.