8

我四处搜寻,要么找不到我要回答的确切问题,要么我需要有人像我 5 岁那样向我解释。

基本上,我有一个使用 Net 库的 Node.js 脚本。我连接到多个主机,发送命令,监听返回数据。

var net = require('net');

var nodes = [
    'HOST1,192.168.179.8',
    'HOST2,192.168.179.9',
    'HOST3,192.168.179.10',
    'HOST4,192.168.179.11'
];

function connectToServer(tid, ip) {
    var conn = net.createConnection(23, ip);
    conn.on('connect', function() {
        conn.write (login_string);  // login string hidden in pretend variable
    });
    conn.on('data', function(data) {
        var read = data.toString();
        if (read.match(/Login Successful/)) {
            console.log ("Connected to " + ip);
            conn.write(command_string);
        }

        else if (read.match(/Command OK/)) { // command_string returned successful,
                                                    // read until /\r\nEND\r\n/

                    // First part of data comes in here
            console.log("Got a response from  " + ip + ':' + read);
        }
        else {
                 //rest of data comes in here
             console.log("Atonomous message from " + ip + ':' + read);
        }
    });
    conn.on('end', function() {
        console.log("Lost conncection to " + ip + "!!");
    });
    conn.on('error', function(err) {
        console.log("Connection error: " + err + " for ip " + ip);
    });
}

nodes.forEach(function(node) {
    var nodeinfo = node.split(",");
    connectToServer(nodeinfo[0], nodeinfo[1]);
});

数据最终被分成两个块。即使我将数据存储在哈希中,并在读取 /\r\nEND\r\n/ 分隔符时将第一部分附加到其余部分,中间也会丢失一个块。如何正确缓冲数据以确保从流中获得完整的消息?

编辑:好的,这似乎效果更好:

function connectToServer(tid, ip) {
        var conn = net.createConnection(23, ip);

        var completeData = '';

        conn.on('connect', function() {
                conn.write (login_string);
        });
        conn.on('data', function(data) {
                var read = data.toString();

                if (read.match(/Login Successful/)) {
                        console.log ("Connected to " + ip);

                        conn.write(command_string);
                }
                else {
                        completeData += read;
                }

                if (completeData.match(/Command OK/)) {
                        if (completeData.match(/\r\nEND\r\n/)) {
                                console.log("Response: " + completeData);
                        }
                }
        });
        conn.on('end', function() {
                console.log("Connection closed to " + ip );
        });
        conn.on('error', function(err) {
                console.log("Connection error: " + err + " for ip " + ip);
        });
}

我最大的问题显然是逻辑错误。我要么在等待开始回复的块,要么在等待结束它的块。我没有保存中间的所有东西。

我想如果我想了解所有关于它的 Node-ish,我应该在收到完整消息时触发一个事件(以空行开头,单独一行以 'END' 结尾),并在那里进行处理。

4

2 回答 2

7

在收到结束事件之前,您不应该对收到的数据做任何事情。结束回调意味着所有数据块都已通过流发送到您的回调。如果数据来自多个块,则需要在函数闭包中创建一个变量来存储这些数据。忽略这一事实,大多数程序都可以正常工作,因为数据通常以一个块的形式出现。但有时它不会。它甚至不一定取决于数据量。如果您遇到这种情况,我创建了一个示例来演示如何处理它。我基本上使用了您的代码,但删除了所有绒毛......这只是演示您收集所有数据并对其进行处理所需的逻辑。

function connectToServer(tid, ip) {
    var conn = net.createConnection(23, ip);
    var completeData = '';

    conn.on('connect', function() {
        conn.write (login_string);  // login string hidden in pretend variable
    });
    conn.on('data', function(data) {
        completeData += data;
        var dataArray = completeData.split('your delimiter');
        if(dataArray.size > 1) { //If our data was split into several pieces, we have a complete chunk saved in the 0th position in the array
            doWorkOnTheFirstHalfOfData(dataArray[0]);
            completeData = dataArray[1];// The second portion of data may yet be incomplete, thise may need to be more complete logic if you can get more than one delimeter at a time...
        }
    });
    conn.on('end', function() {
        //do stuff with the "completeData" variable in here.
    });
}
于 2013-06-26T06:48:03.290 回答
2

我的问题是逻辑问题。我要么在寻找开始消息的块,要么在寻找结束消息的块,而忽略了两者之间的所有内容。我猜预计整个回复会分成一两个块。

这是从上面粘贴的工作代码。可能有一种更 Node-ish 的方法(我真的应该为每个信息块发出一个事件),但我会将此标记为答案,除非有人在明天这个时候发布更好的版本。

function connectToServer(tid, ip) {
        var conn = net.createConnection(23, ip);

        var completeData = '';

        conn.on('connect', function() {
                conn.write (login_string);
        });
        conn.on('data', function(data) {
                var read = data.toString();

                if (read.match(/Login Successful/)) {
                        console.log ("Connected to " + ip);

                        conn.write(command_string);
                }
                else {
                        completeData += read;
                }

                if (completeData.match(/Command OK/)) {
                        if (completeData.match(/\r\nEND\r\n/)) {
                                console.log("Response: " + completeData);
                        }
                }
        });
        conn.on('end', function() {
                console.log("Connection closed to " + ip );
        });
        conn.on('error', function(err) {
                console.log("Connection error: " + err + " for ip " + ip);
        });
}
于 2013-06-27T17:07:08.053 回答