NodeJS TCP客户端通信



首先,我知道类似问题的答案。

问题

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

当我尝试发送消息时,问题就出现了。我需要等待第一条消息的答案,然后再发送第二条消息(比如乒乓球)。

我试着在我的NodeJS tcp客户端上这样写多次,可以理解的是,由于异步:,它失败了

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

正如我之前所说,我有一个第三方组件,它用一个数值来响应这两条消息。所以当

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

引发了一个事件,我分不清是哪条消息,对答案负责。与链接的答案不同,我没有能力在服务器端标记答案。

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

一种方法是使用一个通用的处理程序列表来跟踪请求和响应:

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

最新更新