NodeJS TCP客户端通信

时间:2016-06-09 09:40:08

标签: javascript node.js sockets tcp

首先 - 我知道这个answer类似的问题。

问题

我有第三方协议,它使用TCP \ IP。该协议定义服务器回复收到的每条消息。在客户端(我试图实现),我必须等待服务器的答案。

当我尝试发送消息时,会出现问题。在发送第二条消息之前,我需要等待第一条消息的答案(如乒乓球)。

我尝试在我的NodeJS tcp-client上做多次写操作,由于异步,这可以理解为失败:

categories

就像我之前说过的,我有一个第三方组件,它使用数值响应这两个消息。所以当

client.connect(connectOptions, function () {
  client.write(message1);
  client.write(message2);
}); 
发生事件,我无法分清哪个消息,负责答案。与链接的answer不同,我没有能力在服务器端标记答案。

我是node.js的新手,所以我试着找出解决这类问题的最佳方法,因为它本质上是:在异步环境中做同步事情。

1 个答案:

答案 0 :(得分: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().on('data')处理程序与.flush()函数一起工作,您按顺序发送请求(因此与同步一样)。用法:

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进行响应。在这种情况下,带响应的匹配请求非常容易,您可以避免所有这些混乱。