2013-06-26 8 views
5

Ich habe gesucht, und entweder kann nicht die genaue Frage, die ich versuche zu beantworten, oder ich brauche jemanden, um es mir wie ich zu erklären bin 5.Node.js net library: vollständige Daten von "Daten" Ereignis

Grundsätzlich habe ich ein Node.js Skript mit der Net-Bibliothek. Ich verbinde mich mit mehreren Hosts und sende Befehle und lausche auf Rückgabedaten.

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

Die Daten werden in zwei Teile aufgeteilt. Selbst wenn ich die Daten in einem Hash speichern und den ersten Teil an den Rest anfüge, wenn ich das/\ r \ nEND \ r \ n/Trennzeichen lese, fehlt ein Chunk aus der Mitte. Wie puffere ich die Daten richtig, um sicherzustellen, dass ich die vollständige Nachricht aus dem Stream bekomme?

EDIT: Ok, scheint dies besser zu funktionieren:

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

Mein größtes Problem offenbar Fehler eine Logik war. Ich wartete entweder auf das Stück, das die Antwort begann, oder auf das Stück, das es beendete. Ich habe nicht alles zwischengespeichert.

Ich denke, wenn ich alle Node-ish darüber bekommen wollte, sollte ich ein Ereignis auslösen, wann immer eine vollständige Nachricht kam (beginnend mit einer leeren Zeile, endend mit 'END' auf einer Zeile) und tun die Verarbeitung dort.

+0

Wie erkennen Sie, dass ein Chunk fehlt? Aus den Debug-Meldungen in der Konsole protokolliert? –

+0

Seite-an-Seite-Vergleich mit der manuellen Ausführung. –

Antwort

1

Mein Problem war ein logisches Problem. Ich suchte entweder nach dem Brocken, der die Nachricht begann, oder nach dem Brocken, der die Nachricht beendete, und ignorierte alles dazwischen. Ich vermute, dass die Gesamtheit der Antwort in ein oder zwei Brocken kommen würde.

Hier ist der Arbeitscode, von oben eingefügt. Es gibt wahrscheinlich eine eher knotenartige Art und Weise, dies zu tun (ich sollte wirklich ein Ereignis für jeden Informationsblock ausgeben), aber ich werde dies als die Antwort markieren, es sei denn, morgen wird morgen eine bessere Version veröffentlicht.

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

Sie sollten nichts mit den Daten tun, die Sie empfangen, bis Sie das Endereignis erhalten. Der Rückruf am Ende bedeutet, dass alle Datenblöcke über den Stream an Ihre Rückrufe gesendet wurden. Wenn Daten in mehreren Chunks enthalten sind, müssen Sie eine Variable innerhalb des Funktionsabschlusses erstellen, in der diese Daten gespeichert werden. Die meisten Programme können gut funktionieren, ignorieren diese Tatsache, weil Daten in der Regel in einem Stück kommen. Aber manchmal nicht. Es hängt nicht einmal unbedingt von der Datenmenge ab. Wenn Sie in einer Situation sind, in der dies geschieht, habe ich ein Beispiel erstellt, das zeigt, wie man damit umgeht. Ich habe im Grunde Ihren Code verwendet, aber alle Flusen entfernt ... das ist nur eine Demonstration der Logik, die Sie benötigen, um alle Daten zu sammeln und daran zu arbeiten.

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 Obwohl es so klingt, als ob er das mit dem Hash macht, ist dieser Code mit einer einfachen lokalen Variable ein viel einfacherer (und leichter zu debuggender) Weg, um dasselbe zu tun. –

+0

@JoachimIsaksson - Ich stimme zu, dass der Ansatz mit einer einzelnen Variablen viel besser ist. Ich hatte gerade ein Problem, den Umfang dieser Variablen zu verstehen, indem ich dies über mehrere Geräte machte. –

+0

Ich glaube, ich verstehe das Ende nicht. Wenn ich meinen Code so editiere, dass er wie der obige Code aussieht, bekomme ich anscheinend nie ein "Ende" -Ereignis. Werde ich das bekommen, wenn ich noch verbunden bin? –