AlexSam
@AlexSam

Не всегда доходят данные от сервера на NodeJS клиенту?

Проблема такая: есть сервер написанный на ноде. Сервер открывает TCP сокет: порт и начинает его слушать (Подчеркиваю — не HTTP, обычный TCP сокет). К этому сокету подключаются клиенты (флешовые) и что-то слушают. Специфика работы сервера такова, что клиенты ему практически ничего не шлют, а шлет только сервер. Клиент шлет только команду авторизации при подключении. Сервер же посылает при необходимости клиенту команды. Так вот, довольно часто, примерно в 10% случаев данные от сервера клиенту не доходят. Причем зависимость определить не удается. Иногда может случится так, что сразу после авторизации данные не дойдут, иногда после некоторого промежутка времени. Причем соединение не отпадает и при следующей отсылке данных все доходит нормально.

Так вот вопросы:

— что сделать, чтоб гарантированно быть уверенным в том, что данные доходят?

— если первое не возможно, то как отследить на сервере, что данные дошли до клиента не прибегая к эхо ответам от клиента?

— что за метод socket.pipe(socket) в примере на главной сайта nodejs.org? В доке его не нашел но может он как-то поможет.



Если кто-то сталкивался с подобной ситуацией или хорошо знает работу пакета NET (nodejs.org/api/net.html) — помогите решением проблемы.



P.s. Сервер DEV совсем не нагружен. Только разработчики. Списывали на лаги сети, но 10% случаев это чересчур, учитывая что пинги ходят нормально.
  • Вопрос задан
  • 5098 просмотров
Пригласить эксперта
Ответы на вопрос 4
@PomanoB
Протокол TCP гарантирует доставку данных, мне кажется проблема именно в вашем протоколе прикладного уровня.
Метод pipe() описан тут — nodejs.org/api/stream.html#stream_stream_pipe_destination_options
Вкратце: он соединяет поток чтения данного сокета с потоком записи, переданном в качестве параметра. То есть все, что пришло на данный сокет, будет записано в поток, переданный в качестве параметра, в данном случаем, этот же самый сокет. Таки образом, получается эхо-сервер.
Ответ написан
@cat_crash
Пробовали ли отследить тем же tcpdumpом (wireshark) — уходят ли пакеты с сервера. Приходят ли подтверждения доставки?
Ответ написан
Stdit
@Stdit
Возможно, это связано с неправильной обработкой потока из сокета (сероятнее всего, на клиенте), поскольку вы не пользуетесь carrier или другой буферизацией/делением. Событие data не означает, что в нем содержится именно так строка, которую послала вторая сторона. Там может быть часть из неё, а может быть и несколько строк сразу (зависит от размера данных и размера буфера передачи). Таким образом, данные могут быть потеряны, если например две команды сервера попадают в одно событие «data», заваливая распознавание пакета (на клиенте, в частности, в зависимости от реализации). На этот камень я наступал, способ решения — carrier, какой-нибудь сокетный фреймворк или свой вариант протокола верхнего уровня. Вот пример демонстрирующих тестов:
Скрытый текст
// server.js
var net = require('net');
var server = new net.Server();

process.on('uncaughtException', function (err) {
    console.log(err.stack);
});

server.listen(12345);
server.on('connection', function (connection) {
    console.log('connection');
    connection.on('data', function (data) {
        console.log('server data', data.toString());
        connection.write(data);
    });
    connection.on('end', function () {
        console.log('server end');
    });
});

// client.js
var net = require('net');
var client = new net.Socket();

process.on('uncaughtException', function (err) {
    console.log(err.stack);
});

client.connect(12345);
client.on('connect', function (connection) {
    console.log('connect');
    client.on('data', function (data) {
        console.log('client data', data.toString());
    });
    client.on('end', function () {
        console.log('client end');
    });
});

setTimeout(function () {
    "use strict";
    client.write('string1');
    client.write('string2');
}, 100);

setTimeout(function () {
    "use strict";
    var i = 100000;
    var string = '';
    while (i--) {
        string += i;
    }
    client.write(string);
}, 200);

setTimeout(function () {
    "use strict";
    client.write('string3');
    client.end('string4');
}, 300);


Если моё предположение неверно и вы об этом позаботились, тогда нужно делать tcpdump с фильтром по порту, и смотреть, что и куда приходит и уходит.
Ответ написан
Keenest
@Keenest
Как вариант, попробовать добавить хотя бы одного нефлешового клиента, и делать выводы (относительно локализации проблемы) в зависимости от того все ли сообщения он получает.
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы