Сетевая библиотека Node.js: получение полных данных из события data

Я искал вокруг, и либо не могу найти точный вопрос, на который пытаюсь ответить, либо мне нужен кто-то, кто объяснит мне это, как будто мне 5 лет.

По сути, у меня есть скрипт Node.js, использующий библиотеку Net. Я подключаюсь к нескольким хостам, отправляю команды и прослушиваю возвращаемые данные.

var net = require('net');

var nodes = [
    'HOST1,192.168.179.8',
    'HOST2,192.168.179.9',
    'HOST3,192.168.179.10',
    'HOST4,192.168.179.11'
];

function connectToServer(tid, ip) {
    var conn = net.createConnection(23, ip);
    conn.on('connect', function() {
        conn.write (login_string);  // login string hidden in pretend variable
    });
    conn.on('data', function(data) {
        var read = data.toString();
        if (read.match(/Login Successful/)) {
            console.log ("Connected to " + ip);
            conn.write(command_string);
        }

        else if (read.match(/Command OK/)) { // command_string returned successful,
                                                    // read until /\r\nEND\r\n/

                    // First part of data comes in here
            console.log("Got a response from  " + ip + ':' + read);
        }
        else {
                 //rest of data comes in here
             console.log("Atonomous message from " + ip + ':' + read);
        }
    });
    conn.on('end', function() {
        console.log("Lost conncection to " + ip + "!!");
    });
    conn.on('error', function(err) {
        console.log("Connection error: " + err + " for ip " + ip);
    });
}

nodes.forEach(function(node) {
    var nodeinfo = node.split(",");
    connectToServer(nodeinfo[0], nodeinfo[1]);
});

В итоге данные разделяются на две части. Даже если я сохраню данные в хэше и добавлю первую часть к остатку при чтении разделителя /\ r \ nEND \ r \ n /, в середине отсутствует фрагмент. Как правильно буферизовать данные, чтобы убедиться, что я получил полное сообщение из потока?

РЕДАКТИРОВАТЬ: Хорошо, похоже, работает лучше:

function connectToServer(tid, ip) {
        var conn = net.createConnection(23, ip);

        var completeData = '';

        conn.on('connect', function() {
                conn.write (login_string);
        });
        conn.on('data', function(data) {
                var read = data.toString();

                if (read.match(/Login Successful/)) {
                        console.log ("Connected to " + ip);

                        conn.write(command_string);
                }
                else {
                        completeData += read;
                }

                if (completeData.match(/Command OK/)) {
                        if (completeData.match(/\r\nEND\r\n/)) {
                                console.log("Response: " + completeData);
                        }
                }
        });
        conn.on('end', function() {
                console.log("Connection closed to " + ip );
        });
        conn.on('error', function(err) {
                console.log("Connection error: " + err + " for ip " + ip);
        });
}

Моей самой большой проблемой была логическая ошибка. Я либо ждал кусок, который начал ответ, либо кусок, который закончил его. Я не спасал все промежуточное.

Я думаю, что если бы я хотел получить всю Node-ish об этом, я должен вызывать событие всякий раз, когда приходит полное сообщение (начиная с пустой строки, заканчивая 'END' на отдельной строке), и делать обработка там.

7 голосов | спросил coding_hero 26 J0000006Europe/Moscow 2013, 09:34:00

2 ответа


0

Моя проблема была логической проблемой. Я либо искал кусок, который начал сообщение, либо кусок, который закончил сообщение, и игнорировал все промежуточное. Я предполагаю, что весь ответ будет представлен в виде одного или двух фрагментов.

Вот рабочий код, вставленный сверху. Вероятно, есть более удобный способ сделать это (я действительно должен генерировать событие для каждой порции информации), но я отмечу это как ответ, если кто-то завтра не отправит лучшую версию.

function connectToServer(tid, ip) {
        var conn = net.createConnection(23, ip);

        var completeData = '';

        conn.on('connect', function() {
                conn.write (login_string);
        });
        conn.on('data', function(data) {
                var read = data.toString();

                if (read.match(/Login Successful/)) {
                        console.log ("Connected to " + ip);

                        conn.write(command_string);
                }
                else {
                        completeData += read;
                }

                if (completeData.match(/Command OK/)) {
                        if (completeData.match(/\r\nEND\r\n/)) {
                                console.log("Response: " + completeData);
                        }
                }
        });
        conn.on('end', function() {
                console.log("Connection closed to " + ip );
        });
        conn.on('error', function(err) {
                console.log("Connection error: " + err + " for ip " + ip);
        });
}
ответил coding_hero 27 J0000006Europe/Moscow 2013, 21:07:08
0

Вы не должны ничего делать с полученными данными, пока не получите конечное событие. Конечный обратный вызов означает, что все фрагменты данных были отправлены через поток в ваши обратные вызовы. Если данные поступают более чем в один блок, вам нужно создать переменную в закрытии вашей функции для сохранения этих данных. Большинство программ могут нормально работать, игнорируя этот факт, потому что данные обычно попадают в один блок. Но иногда это не так. Это даже не обязательно зависит от объема данных. Если вы находитесь в ситуации, когда это происходит, я создал пример, демонстрирующий, как с этим справиться. Я в основном использовал ваш код, но удалил весь пух ... это просто демонстрирует логику, необходимую для сбора всех данных и работы над ними.

function connectToServer(tid, ip) {
    var conn = net.createConnection(23, ip);
    var completeData = '';

    conn.on('connect', function() {
        conn.write (login_string);  // login string hidden in pretend variable
    });
    conn.on('data', function(data) {
        completeData += data;
        var dataArray = completeData.split('your delimiter');
        if(dataArray.size > 1) { //If our data was split into several pieces, we have a complete chunk saved in the 0th position in the array
            doWorkOnTheFirstHalfOfData(dataArray[0]);
            completeData = dataArray[1];// The second portion of data may yet be incomplete, thise may need to be more complete logic if you can get more than one delimeter at a time...
        }
    });
    conn.on('end', function() {
        //do stuff with the "completeData" variable in here.
    });
}
ответил ChrisCM 26 J0000006Europe/Moscow 2013, 10:48:03

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

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132