2013-06-26 11 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]); 
}); 

データは2つのチャンクに分割されます。/\ r \ nEND \ r \ n /区切り文字を読み込んだときに、データをハッシュに格納して最初の部分を残りの部分に追加しても、途中で欠落したチャンクがあります。ストリームから完全なメッセージを確実に取得するために、データを適切にバッファリングするにはどうすればよいですか?

EDIT:OK、これはより良い動作しているようだ:

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

私の問題は論理的な問題でした。私は、メッセージを開始したチャンク、またはメッセージを終了したチャンクを探していて、間にあるすべてを無視していました。私は返信の全体が1つか2つのチャンクで来ると思っています。

ここに、上から貼り付けられた作業コードです。おそらく、それを行うための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

終了イベントを受け取るまで、受信するデータは何もしないでください。エンドコールバックとは、すべてのデータチャンクがストリームを通じてコールバックに送信されたことを意味します。データが複数のチャンクに入っている場合は、このデータを格納する変数を関数クロージャ内に作成する必要があります。ほとんどのプログラムは、データが通常は1つのチャンクに渡ってくるので、この事実を無視してうまく動作します。しかし時にはそうではありません。それはデータの量に必ずしも依存しません。これが起こっている状況にいる場合は、それを処理する方法をデモするサンプルを作成しました。私は基本的にあなたのコードを使用しましたが、すべての綿毛を除去...これは、あなたはすべてのデータを収集し、それで動作する必要があるロジックをデモだけです。

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

私は 'end'イベントを理解していないと思います。上記のコードのようにコードを編集すると、私は決して終わりのイベントを得られないようです。私はまだ接続されている場合、私はそれを取得するつもりですか? –

関連する問題