2013-06-26 1 views
5

Я искал вокруг, и либо не могу найти точный вопрос, на который я пытаюсь ответить, либо мне нужен кто-то, чтобы объяснить это мне, как я 'm 5.Node.js net library: получение полных данных из события «данные»

В принципе, у меня есть сценарий 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/разделитель, есть кусок, отсутствующий посередине. Как правильно буферизовать данные, чтобы получить полное сообщение из потока?

EDIT: Хорошо, это, кажется, работает лучше:

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» на отдельной строке), и делайте обработка там.

+0

Как вы обнаруживаете, что кусок отсутствует? От сообщений отладки, зарегистрированных на консоли? –

+0

бок о бок сравнение с выполнением этого вручную. –

ответ

1

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

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

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); 
     }); 
} 
3

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

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. 
    }); 
} 
+0

+1 Хотя это похоже на то, что он делает с хэшем, этот код с простой локальной переменной гораздо проще (и проще отлаживать) способ сделать то же самое. –

+0

@JoachimIsaksson - Я согласен с тем, что подход с одной переменной намного лучше, у меня просто возникла проблема с пониманием области действия этой переменной, когда вы делаете это на нескольких устройствах. –

+0

Я думаю, что я не понимаю событие «конец». Когда я редактирую свой код, чтобы выглядеть как код выше, я, похоже, никогда не получаю событие «конец». Пойду ли я, если я все еще подключусь? –

Смежные вопросы