2016-06-09 206 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。我想,我会采用第二种方法,我必须先尝试一下,但对于我所看到的可能会解决我的问题。 –