通过套接字发送命令,但每次都等待响应(Node.js)

Posted

技术标签:

【中文标题】通过套接字发送命令,但每次都等待响应(Node.js)【英文标题】:Send commands over socket, but wait every time for response (Node.js) 【发布时间】:2011-10-23 15:36:46 【问题描述】:

我需要通过 telnet 向服务器发送几个命令。如果我尝试在每个命令之间没有时间延迟地发送它们,服务器就会崩溃:

var net = require('net');
var conn = net.createConnection(8888, 'localhost');
conn.on('connect', function() 
    conn.write(command_1);
    conn.write(command_2);  
    conn.write(command_3);
    //...
    conn.write(command_n);
)

我猜服务器需要一些时间来响应命令n,然后再发送命令n+1。一种方法是在日志中写入一些内容并假装“等待”:

var net = require('net');
var conn = net.createConnection(8888, 'localhost');
conn.on('connect', function() 
    console.log('connected to server');
    console.log('I'm about to send command #1');
    conn.write(command_1);
    console.log('I'm about to send command #2');
    conn.write(command_2);  
    console.log('I'm about to send command #3');
    conn.write(command_3);
    //...
    console.log('I'm about to send command #n');
    conn.write(command_n);
)

也可能是 conn.write() 是异步的,并且将一个命令一个接一个并不能保证正确的顺序??

无论如何,确保正确顺序和两个连续命令之间有足够时间让服务器响应的正确模式是什么?

【问题讨论】:

“服务器崩溃了”是什么意思? 【参考方案1】:

首先要做的事情:如果这确实是一个 telnet 服务器,那么您应该使用 telnet 握手来做一些事情(终端选项在对等方之间协商,这是您在打开套接字时可以看到的二进制数据)。

如果您不想参与其中(这取决于您的需求),您可以忽略谈判并直接开展业务,但您必须自己阅读这些数据并忽略它。

现在,在您的代码中,您将在服务器接受连接后立即发送数据。这可能是您遇到麻烦的原因。您不应该“等待”响应,由于nodejs,响应将异步发送给您:)因此,您只需从服务器获得“正确”响应后立即发送命令(这实际上是有用,因为您可以查看是否有任何错误等)。

我已经在我手头的具有 telnet 服务器的设备上尝试了此代码(基于您的代码)。它将进行登录,然后注销。查看如何根据服务器的响应分派事件:

var net = require('net');
var conn = net.createConnection(23, '1.1.1.1');
var commands = [ "logout\n" ];
var i = 0;
conn.setEncoding('ascii');
conn.on('connect', function() 
    conn.on('login', function () 
        conn.write('myUsername\n');
    );
    conn.on('password', function () 
        conn.write('myPassword\n');
    );
    conn.on('prompt', function () 
        conn.write(commands[i]);
        i++;
    );
    conn.on('data', function(data) 
        console.log("got: " + data + "\n");
        if (data.indexOf("login") != -1) 
            conn.emit('login');
        
        if (data.indexOf("password") != -1) 
            conn.emit('password');
        
        if (data.indexOf(">#") != -1) 
            conn.emit('prompt');
        
    );
);

查看命令如何在数组中,您可以在其中迭代发送它们(提示事件将触发下一个命令)。因此,来自服务器的正确响应是下一个提示。当服务器发送(在这种情况下)字符串 ># 发送另一个命令。

希望对你有帮助:)

【讨论】:

【参考方案2】:

保证写入的顺序。然而:

    您必须订阅数据事件。 conn.on('数据',函数(数据) ) 会。 您必须检查写入的返回值 - 如果写入 失败,你必须等待'drain'事件。所以你应该检查是否有 write 确实失败了,如果确实如此,则可以解决问题。如果它 没有 - 那么你可以保留当前的肮脏解决方案。 你 必须检查您的服务器是否支持请求流水线(发送 多个请求而不等待响应)。如果没有—— 在收到数据事件之后,您不得发送下一个请求 上一个。 您必须确保您发送的命令是真正的 telnet 命令 - telnet 需要在 \r\n 之后有一个 \0 字节(请参阅 RFC),因此如果 \0 不存在,某些服务器可能会崩溃。

所以:

var net = require('net');
var conn = net.createConnection(8888, 'localhost');
conn.on('connect', function() 
    console.log(conn.write(command_1) && 
    conn.write(command_2) &&
    conn.write(command_3) &&
    //...
    conn.write(command_n))

)
conn.on('data', function () )

如果它写入 false - 那么你必须等待'drain'。如果它写成真 - 你必须实现等待。我不鼓励使用基于事件的解决方案,并建议改用 async 或 Step NPM 模块。

【讨论】:

以上是关于通过套接字发送命令,但每次都等待响应(Node.js)的主要内容,如果未能解决你的问题,请参考以下文章

Redis六(管道)

通过写入 DataOutputStream 通过蓝牙向设备发送命令

如何在接收响应时通过 websocket 发送请求

redis使用管道pipeline提升批量操作性能(php演示)

redis学习教程五《管道分区》

redis性能提升之pipeline