读取 Node.js 中的套接字连接响应


Reading socket connection responses in Node.js

我正在将PHP函数转换为JS以与Node一起使用。

PHP 函数:

  • 将部分形成的数据包作为参数
  • 完成数据包
  • 创建套接字
  • 通过套接字发送数据包
  • 从服务器读取响应代码
  • 查找数组中的错误代码
  • 将错误代码发送回调用方

我已经转换了大部分函数,除了读取服务器响应的位。

原创的PHP函数(注释是我对代码功能的理解。可能不正确)

    function serverInteractive($buf) { // $buf = partially formed packet
    $fp = fsockopen($ip, $port , $errno, $errstr, 5);
    $rs = '';
    if (!$fp) return $this -> fsockerror;
    $packet = pack("s", (strlen($buf)+2)).$buf; // Finalizes the packet
    fwrite($fp, $packet); // Sends the packet to the server.
            // ----- Read Server Response START -----//
    $len = unpack("v", fread($fp, 2));
    $rid = unpack("c", fread($fp, 1));
    for ($i = 0; $i < (($len[1] - 4) / 4); $i++) { 
        $read = unpack("i", fread($fp, 4));
        $rs .= $read[1];
    }
            // ----- Read Server Response FINISH -----//
    fclose($fp); // Closes the socket
    $result = $this -> socketerrors[$rs]; 
            // $socketerrors is an array of error messages.
return($result);
}

我的JavaScript版本

var net = require('net');
var submitPacket = function(packet) {
    // Generate Final Packet
    var p = pack('s', packet.length + 2) + packet;
    // Create socket to Server
    var serverSocket = net.createConnection(config.serverConfig.port,
                                            config.serverConfig.host,
        function() {
         // Executes of connection is OK.
            console.log("Connected to Server");
            if (serverSocket.write(p, function() {
                console.log("Buffer Flushed!");
            })) {
                console.log("Packet sent ok!");
            } else {
                console.log("There was a problem sending the packet!")
            }
        });
    serverSocket.on('error', function(error) {
        if (error) {
            console.log(error);
        }
    });
    serverSocket.on('data', function(data) {
        if (data) {
            console.log("Response: ", data);
           // Need to put the error code generation
           // here and fire a callback.
            serverSocket.end();
        }
    });
}

当一切正常时,我从服务器得到的响应看起来像这样:

<Buffer 07 00 06 01 00 00 00>

当不正常时,看起来像这样:

<Buffer 0b 00 06 00 00 00 00 03 00 00 00>

任何建议将不胜感激。

更新1:这是我到目前为止想出的,但是生成的代码尚未定义。

serverdSocket.on('data', function(data) {
        if (data) {
        var response = toArrayBuffer(data);
        var len = response.slice(0,2);
        var rid = response.slice(0,1);
        var rs = '';
        for (var i = 0; i < ((len[1]-4) / 4); i++) {
            var read = response.slice(0,4);
            rs += read[1];
        }
        console.log("Code: ",rs);
    }

更新2:PHP unpack 函数确实将二进制数据的缓冲区转换为数组。看起来我可以通过 JSON.stringify 然后 JSON.parse() 做同样的事情来让它进入数组。我现在有一个正确数据的数组对象,但函数的其余部分似乎没有复制原始数据。

我会试一试,尽管您实际上还没有说出您希望两个输入字符串的"Code:"输出是什么样子。我们将从 PHP 代码和 JavaScript 代码之间的差异开始。

让我们谈谈 PHP 代码中的这些行:

$len = unpack("v", fread($fp, 2));
$rid = unpack("c", fread($fp, 1));

现在,这些小fread()函数调用实际上是从输入流/文件/任何内容中读取数据。底线是$len从流的前两个字节获取其值,$rid第三个字节获取其值。

现在与 JavaScript 代码进行比较:

    var len = response.slice(0,2);
    var rid = response.slice(0,1);

我对这段代码有一些观察。首先,对slice()的调用都对同一个类似数组的对象进行操作,从同一位置开始。所以rid的价值将是错误的。其次,示例代码中从未使用 rid 的值,因此如果您从未真正需要它,则可以完全消除该行(这在 PHP 代码中无法做到)。第三个观察结果是,打电话给slice()似乎矫枉过正。为什么不只在response上使用方括号?

关于原始PHP代码的最后一个难题。查看构建$rs的代码:

$rs .= $read[1];

看起来这是连续整数数据值的字符串串联。我已经在PHP工作了几年了,所以也许我错过了一些微妙之处,但这似乎是一件奇怪的事情。如果您能告诉我预期的输出代码应该是什么,那将有所帮助。

这就引出了数据本身。只是从 PHP 代码中的数据示例中猜测,看起来前两个字节是小端编码的 16 位缓冲区长度。下一个字节是rid值,在两个示例中均为 6。然后看起来缓冲区的其余部分由 32 位小端值组成。当然,这是一个 WAG,但我只是在使用所提供的东西。

因此,下面是一些处理来自两个示例缓冲区的数据值的代码。对于第一个缓冲区,它打印Code: 1,对于第二个Code: 03。如果这些不是正确的值,那么让我知道预期的输出是什么,我会看看我是否可以让它工作。

function toArrayBuffer(buffer) {
    var ab = new ArrayBuffer(buffer.length);
    var view = new Uint8Array(ab);
    for (var i = 0; i < buffer.length; ++i) {
        view[i] = buffer[i];
    }
    return ab;
}
function serverSocketOnData(data)
{
    if (data) {
        var response = toArrayBuffer(data);
        var len = response[0] + 256*response[1];
        var rid = response[2]; // get rid of this line?
        var rs = '';
        for (var i = 3; i < len; i+=4) {
            rs += response[i];
            // if the 32-bit value could ever exceed 255, then use this instead:
            // rs += response[i] + 256*response[i+1] +
            //       256*256*response[i+2] + 256*256*256*response[i+3];
        }
        console.log("Code: ",rs);
    }
}
function testArray(sourceArray)
{
    var sourceBuffer = new Buffer(sourceArray);
    console.log("source buffer");
    console.log(sourceBuffer);
    serverSocketOnData(sourceBuffer);
}
function main()
{
    var sourceArray1 = [0x07,0x00,0x06,0x01,0x00,0x00,0x00];
    var sourceArray2 = [0x0b,0x00,0x06,0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x00];
    testArray(sourceArray1);
    testArray(sourceArray2);
}
main();

你是否恰当地使用slice

当您在字符串上调用 slice 时,它会返回一个字符串。

var hello = "hello"
var hel = hello.slice(0, 3)
var h = hel[1]
var ello = hello.slice(1)