2016-06-09 209 views
0

首先 - 我知道這個answer是一種類似的問題。NodeJS TCP客戶端通訊

問題

我有一個第三方協議,使用TCP \ IP。該協議定義服務器回覆收到的每條消息。在客戶端(我試圖實現),我必須等待來自服務器的答案。

當我嘗試發送消息時會出現問題。在發送第二條消息(比如乒乓球)之前,我需要等待第一條消息的答案。

我試圖做我的NodeJS TCP客戶端這樣的,這可以理解失敗,因爲異步多寫道:

client.connect(connectOptions, function() { 
    client.write(message1); 
    client.write(message2); 
}); 

就像我之前說的,我有一個第三方組件,其中兩個消息的響應與一個數字值。所以當

client.on('data',function (data) {}); 

火災事件,我無法區分哪個消息,負責答案。與鏈接的answer不同,我沒有能力在服務器端標記答案。

我是node.js的新手,所以我試圖找出解決這類問題的最佳方法,因爲它的本質是:在異步環境中做同步事情。

回答

0

一種方法是使用處理器的一個共同列表可跟蹤的請求和響應:

var handlers = []; 
client.connect(connectOptions, function() { 
    client.write(message1); 
    handlers.push(function msg1_handler(data) {}); 

    client.writewrite(message2); 
    handlers.push(function msg2_handler(data) {}); 
}); 
client.on('data',function(data) { 
    var handler = handlers.shift(); 
    handler(data); 
}); 

所有這一切都應該明顯含有handlersclient對象單獨的一類包裹。這只是一個如何去做的例子。缺點是,如果服務器無法響應某些請求,那麼你有一個完整的混亂,很難做出正確的決定。


另一個想法是緩衝區的請求:

function BufferedClient(cli) { 
    this.cli = cli; 
    this.buffer = []; 
    this.waiting_for_response = false; 
    var that = this; 
    cli.on('data', function(data) { 
     that.waiting_for_response = false; 
     var pair = that.buffer.shift(); 
     var handler = pair[0]; 
     process.nextTick(function() { 
      // we use .nextTick to avoid potential 
      // exception in handler which would break 
      // BufferedClient 
      handler(data); 
     }); 
     that.flush(); 
    }); 
}; 
BufferedClient.prototype = { 
    request: function(msg, handler) { 
     this.buffer.push([handler, msg]); 
     this.flush(); 
    }, 
    flush: function() { 
     var pair = this.buffer[0]; 
     if (pair && !this.waiting_for_response) { 
      this.cli.write(pair[1]); 
      this.waiting_for_response = true; 
     } 
    } 
}; 

這個時候你按順序發送請求(所以像同步)由於如何.request().flush()功能.on('data')處理器一起工作。使用方法:

client.connect(connectOptions, function() { 
    var buff_cli = new BufferedClient(client); 
    buff_cli.request(message1, function(data) { }); 
    buff_cli.request(message2, function(data) { }); 
}); 

現在,即使服務器無法響應,也不會有一團糟。但是,如果您並行發出buff_cli.request,並且其中一個失敗,那麼您將有內存泄漏(因爲this.buffer正在變大,而沒有任何東西正在耗盡,因爲BufferedClient正在等待響應)。這可以通過在套接字上添加一些超時來解決。

請注意,這兩種解決方案都假定服務器在沒有請求的情況下從不向客戶端推送任何內容。

如果我是你,我會去第二個解決方案。請注意,我沒有測試代碼,所以它可能是越野車,但一般的想法應該沒問題。

附註:當你實現一個服務器(並且我知道你並不是這種情況)時,你應該總是有一個協議,以一種獨特的方式將每個請求與一個響應進行匹配。一種方法是在每個請求中發送一個唯一的ID,以便服務器可以使用相同的ID進行響應。在這種情況下,將請求與響應進行匹配非常容易,您可以避免所有這些混亂。

+0

Thx。我想,我會採用第二種方法,我必須先嚐試一下,但對於我所看到的可能會解決我的問題。 –