Форум программистов, компьютерный форум, киберфорум
Node.js
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.94/33: Рейтинг темы: голосов - 33, средняя оценка - 4.94
0 / 0 / 0
Регистрация: 22.06.2017
Сообщений: 2

Дублируются сообщения при отправке конкретному пользователю через socket.io

22.06.2017, 13:31. Показов 6378. Ответов 2
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Всем добрый день!
Такая проблема. Делаю простой чат, в котором можно отправлять сообщения конкретным пользователям. Есть клиенты и есть операторы.Но есть проблема, если подключены несколько клиентских сокетов и мы отправляем сообщение на один из них, то сообщение дублируется у клиента, которому отправляем его. Допустим, если подключены два клиентских сокета,то у получателя сообщение дублируется 2 раза. Если 3 сокета, то 3 раза. А если подключен только один клиент, то у него сообщение не дублируется. Сообщения конкретному клиенту пробовал отправлять через socket.to(socketID)... и через socket.broadcast.to(socketID)...... Подскажите, пожалуйста.

Код сервера:

JavaScript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
var app = require('express')();
var server = require('http').Server(app);
var io = require('socket.io')(server);
var redis = require('redis');
 
server.listen(8890);
 
io.on('connection', function (socket) {
 
console.log("new client connected");
 
var redisClient = redis.createClient();
 
redisClient.subscribe('notification');
 
 
redisClient.on("message", function (channel, message) {
    console.log("New message: " + message + ". In channel: " + channel);
    var json = JSON.parse(message);
    if (json.clientId != '' && json.operatorId == '') {
        socket.emit('newClient', message);
        socket.to(json.clientId).emit('notification', message);
        console.log(1);
    } else if (json.clientId != '' && json.operatorId != '') {
        socket.broadcast.to(json.clientId).emit('notification', message);
        socket.broadcast.to(json.operatorId).emit('notification', message);
        console.log(2);
    } else {
        console.log('не вышло');
    }
});
 
socket.on('disconnect', function () {
    redisClient.quit();
});
 
});
Код клиента:
JavaScript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
jQuery(function ($) {
    $(document).ready(function () {
 
        var
                socket = io.connect('http://localhost:8890'),
                socketId;
 
        socket.on('connect', function () {
            socketId = socket.id;
            $('#chat-form input[name=client-id]').val(socketId);
        });
 
        socket.on('notification', function (data) {
 
            var message = JSON.parse(data);
 
            if (message.operatorId) {
                $('#chat-form input[name=operator-id]').val(message.operatorId);
            }
            $("#notifications").prepend("<p><strong>" + message.name + "</strong>: " + message.message + "</p>");
 
        });
 
    });
});
Код оператора:

JavaScript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
jQuery(function ($) {
    $(document).ready(function () {
 
        var socket = io.connect('http://localhost:8890');
 
        socket.on('connect', function () {
            socketId = socket.id;
            $('#chat-form input[name=operator-id]').val(socketId);
 
        });
 
        socket.on('notification', function (data) {
 
            var message = JSON.parse(data);
 
            $("#notifications").prepend("<p><strong>" + message.name + "</strong>: " + message.message + "</p>");
 
        });
 
        socket.on('newClient', function (data) {
            var message = JSON.parse(data);
            alert(message.clientId + ' присоединился!');
            if (message.clientId) {
                $('#chat-form input[name=client-id]').val(message.clientId);
            }
 
        });
 
    });
});
0
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
22.06.2017, 13:31
Ответы с готовыми решениями:

Ошибка: Socket WouldBlock, при отправке сообщения от сервера к клиенту
Привет, есть некий сервер, раньше работало все четко, а после последних изменений (незначительных) стала вылазить ошибка в сабже, и только...

Сокеты: ошибка при отправке сообщения через сервер
Если отправляю сообщение через сервер, то выбивает ошибку &quot;Windows Socket error:Запрос на отправку или получение данных (When sending on a...

При отправке AJAX дублируются запросы
Имеется такой вот скрипт. $('.container').on('click', '', function (){ var type = $('.container ').data('type'); ...

2
Coding is art
Эксперт JS
540 / 423 / 154
Регистрация: 04.09.2013
Сообщений: 1,066
22.06.2017, 23:02
JavaScript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
var redisClient = redis.createClient();
 
redisClient.subscribe('notification');
 
 
redisClient.on("message", function (channel, message) {
    console.log("New message: " + message + ". In channel: " + channel);
    var json = JSON.parse(message);
    if (json.clientId != '' && json.operatorId == '') {
        socket.emit('newClient', message);
        socket.to(json.clientId).emit('notification', message);
        console.log(1);
    } else if (json.clientId != '' && json.operatorId != '') {
        socket.broadcast.to(json.clientId).emit('notification', message);
        socket.broadcast.to(json.operatorId).emit('notification', message);
        console.log(2);
    } else {
        console.log('не вышло');
    }
});
Вам вот эту часть кода нужно вынести из .on('connection', ... ) функции..

Получается, что каждый раз когда кто-то заходит на сокет вы создаёте новое редис подключение и вешаете событие на отлов сообщений редиса.

это как в хендлере клика вешать слушатель на передвежение мыши..
каждый раз как вы будете кликать будет ещё 1-н слушатель передвежения мыши..
0
0 / 0 / 0
Регистрация: 22.06.2017
Сообщений: 2
26.07.2017, 11:36  [ТС]
Цитата Сообщение от muxahuk1214 Посмотреть сообщение
Вам вот эту часть кода нужно вынести из .on('connection', ... ) функции..
Получается, что каждый раз когда кто-то заходит на сокет вы создаёте новое редис подключение и вешаете событие на отлов сообщений редиса.
это как в хендлере клика вешать слушатель на передвежение мыши..
каждый раз как вы будете кликать будет ещё 1-н слушатель передвежения мыши..
А подскажите тогда, пожалуйста, как быть, чтобы nodejs сервер создавал только одну подписку на редис при старте и всегда ее слушал, или это невозможно? Я наверно не понимаю как устроена работа nodejs. Сервер вешает обработчики событий, только когда на него подключаются клиенты или просто при старте сервера он устанавливает обработчики событий сам? Спасибо
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
26.07.2017, 11:36
Помогаю со студенческими работами здесь

Ошибка IP при отправке socket
Прошу прощенья если такое были, просто не знаю даже как гуглить (а похожих тем не нашлось автоматически). В общем беда такого рода: Я...

Как создать програмно автозагрузку конкретному пользователю через реестр?
У меня на компьютере созданы пользователи для детей. Я хочу добавить свою программу (контроль времени) в автозагрузку реестра конкретному...

Ошибка при отправке сообщения
Доброго времени суток. При отправке сообщения возникает ошибка: Порт 25, сервер smtp.gmail.com. Как можно решить данную проблему?

Исключение при отправке сообщения
При отправке сообщения появляется исключение: Client does not have permissions to send as this sender. Какие будут советы? public...

Socket не отсылает сообщения через SEND и не принимает
Когда конектится клиент с сервером, сервер должен отображать то, что передает клиент, т.е. asdf, но он ничего не отображает. В другую...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
3
Ответ Создать тему
Новые блоги и статьи
SDL3 для Web (WebAssembly): Обработчик клика мыши в браузере ПК и касания экрана в браузере на мобильном устройстве
8Observer8 02.02.2026
Содержание блога Для начала пошагово создадим рабочий пример для подготовки к экспериментам в браузере ПК и в браузере мобильного устройства. Потом напишем обработчик клика мыши и обработчик. . .
Философия технологии
iceja 01.02.2026
На мой взгляд у человека в технических проектах остается роль генерального директора. Все остальное нейронки делают уже лучше человека. Они не могут нести предпринимательские риски, не могут. . .
SDL3 для Web (WebAssembly): Вывод текста со шрифтом TTF с помощью SDL3_ttf
8Observer8 01.02.2026
Содержание блога В этой пошаговой инструкции создадим с нуля веб-приложение, которое выводит текст в окне браузера. Запустим на Android на локальном сервере. Загрузим Release на бесплатный. . .
SDL3 для Web (WebAssembly): Сборка C/C++ проекта из консоли
8Observer8 30.01.2026
Содержание блога Если вы откроете примеры для начинающих на официальном репозитории SDL3 в папке: examples, то вы увидите, что все примеры используют следующие четыре обязательные функции, а. . .
SDL3 для Web (WebAssembly): Установка Emscripten SDK (emsdk) и CMake для сборки C и C++ приложений в Wasm
8Observer8 30.01.2026
Содержание блога Для того чтобы скачать Emscripten SDK (emsdk) необходимо сначало скачать и уставить Git: Install for Windows. Следуйте стандартной процедуре установки Git через установщик. . . .
SDL3 для Android: Подключение Box2D v3, физика и отрисовка коллайдеров
8Observer8 29.01.2026
Содержание блога Box2D - это библиотека для 2D физики для анимаций и игр. С её помощью можно определять были ли коллизии между конкретными объектами. Версия v3 была полностью переписана на Си, в. . .
Инструменты COM: Сохранение данный из VARIANT в файл и загрузка из файла в VARIANT
bedvit 28.01.2026
Сохранение базовых типов COM и массивов (одномерных или двухмерных) любой вложенности (деревья) в файл, с возможностью выбора алгоритмов сжатия и шифрования. Часть библиотеки BedvitCOM Использованы. . .
SDL3 для Android: Загрузка PNG с альфа-каналом с помощью SDL_LoadPNG (без SDL3_image)
8Observer8 28.01.2026
Содержание блога SDL3 имеет собственные средства для загрузки и отображения PNG-файлов с альфа-каналом и базовой работы с ними. В этой инструкции используется функция SDL_LoadPNG(), которая. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru