2016-09-19 4 views
1

私はNode.JSの基礎を教える本を読んでいます。私は1つのレスポンダと1つのリクエスタという2つのプログラムを作成しました。リクエストメッセージとレスポンスメッセージが順不同ですか?

応答:

"use strict"; 

const fs = require("fs"); 
const zmq = require("zmq"); 
const responder = zmq.socket("rep"); // Create socket to reply to client requests 

// Handle incoming requests 
responder.on("message", function(data) { 
    // Parse incoming message 
    let request = JSON.parse(data); 
    console.log("Received request to get: " + request.path); 

    // Read file and reply with content 
    fs.readFile(request.path, function(err, content) { 
     console.log("Sending response content"); 
     responder.send(JSON.stringify({ 
      content: content.toString(), 
      timestamp: Date.now(), 
      pid: process.pid 
     })); 
    }); 
}); 

// Listen on TCP port 5433 
responder.bind("tcp://127.0.0.1:5433", function(err) { 
    console.log("Listening for zmq requesters..."); 
}); 

// Close the responder when the Node process ends 
process.on("SIGINT", function() { 
    console.log("Shutting down..."); 
    responder.close(); 
}); 

依頼者:

"use strict"; 

const zmq = require("zmq"); 
const filename = process.argv[2]; 
const requester = zmq.socket("req"); // Create request endpoint 

// Handle replies from responder 
requester.on("message", function(data) { 
    let response = JSON.parse(data); 
    console.log("Received response:", response); 
}); 

requester.connect("tcp://localhost:5433"); 

// Send request for content 
for (let i=1; i <= 3; i++) { 
    console.log("Sending request " + i + " for " + filename); 
    requester.send(JSON.stringify({ 
     path: filename 
    })); 
} 

だから私はその後、私はこのような要求元のプログラムは、(target.txtすでにファイルシステム上に存在して実行し、罰金を起動し、応答プログラムを実行します):

> node requester.js target.txt 

奇妙なことは、Node.jsのシングルスレッドでは、私はへの出力は、常にがあること期待:

Sending request 1 for target.txt 
Sending request 2 for target.txt 
Sending request 3 for target.txt 
Received response: { ... 

しかし、時々私はそれを取得しますが、時々私は取得しています:

Sending request 1 for target.txt 
Sending request 2 for target.txt 
Received response: { ... 
Sending request 3 for target.txt 

はどのようにこれをすることができますか?イベントループは私の forループを実行しています。これは "送信要求"行が出力され、応答ハンドラを呼び出す機会があることを意味します。 3番目のリクエストがログに記録される前に、時々レスポンスが記録されるのはなぜですか?

+0

私は、ネットワークの不確実な性質を考えると、要求/応答の順序に頼るべきではないと思います。 あなたはrequest1と今度はrequest2とrequest3を作ることができますが、あなたはどんな順序でも応答を得ることができます。 – klikas

+0

@klikas Node.jsのシングルスレッドの性質を理解していますか? – Jez

+0

Node.jsがシングルスレッドであることを理解していますが、現実のシナリオでは、リクエストが常に特定の順序でサーバーにヒットすることを実際にどのように保証できるのか分かりません。 – klikas

答えて

2

表示されている動作は、onに提供されたコールバックがsendの実装から呼び出された場合にのみ発生します。

zmqモジュールにはネイティブコードが含まれています。ネイティブコードで応答を受け取り、JavaScriptホストが応答を利用できるようにします。レスポンスの受信は、JavaScriptのイベントループに束縛されません。 sendの実装では、応答が利用可能な場合、onに提供されたコールバックが呼び出されます。おそらく、sendコール内のコールバックに渡されなかった応答は、次のターンにイベントループを通過します。

+0

またはすべての応答がイベントループを完全にバイパスしますか? ZMQが独自のスレッドを使って 'on(" message "...'コールバックを実行している場合、なぜNode.jsのイベントループを心配する必要がありますか? – Jez

+0

別のスレッドでJavaScriptコールバックを実行できません。 – cartant

+0

JavaScriptをシングルスレッド化する方法メインイベントループが 'Sending request'をコンソールに記録している最中に、ZMQが表示されます – Jez

-1

responder関数でファイルを読み取るときは、非同期ノンブロッキング関数(新しいスレッドでファイルを読み込みます)であるfs.readFileを使用します。これは、新しい要求を受け入れる前にファイルが読み込まれるのを待つことを意味します。

あなたはこのファイルが完全に読み込まれるのを待ち、その後、応答を送信します

fs.readFileSync 

を使用することができ、同期機能を使用したい場合。

+0

それは私の問題ではありません。私の要点は、要求者プログラムが、応答が到着しても3つの要求すべてを出力しなければならないことをNode.jsのシングルスレッドの性質が意味しなければならないにもかかわらず、3つの要求すべてを出力する前にコンソール*その間。 – Jez

+0

多分私はまだ不足していない。しかし、 'fs.readFile'を使うと、別のスレッドでそれを行います。したがって、ファイルの読み込み速度に応じて、順序が変更される可能性があります。 ファイルを読み込むすべての要求が別のスレッドで同時に実行され、次に最速のものが最初に返されるようになる可能性があります –

関連する問題