2013-06-26 52 views
5

我搜索了四周,並且找不到確切的問題,我想要回答,或者我需要有人像我一樣向我解釋它'm 5.Node.js網絡庫:從'data'事件獲取完整數據

基本上,我有一個使用Net庫的Node.js腳本。我連接到多個主機,併發送命令,並偵聽返回數據。

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'),在那裏處理。

+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

我想我不明白'結束'事件。當我編輯我的代碼看起來像上面的代碼,我似乎從來沒有得到'結束'事件。如果我仍然連線,我會得到嗎? –