【问题标题】:NodeJS Javascript for loop changing contents用于循环更改内容的 NodeJS Javascript
【发布时间】:2014-07-07 20:35:10
【问题描述】:

我有以下代码迭代 Buffer 以查找数据包结束标记。这个 Buffer 对象中可能有几个数据包,所以我使用数据包标记来查找数据,处理它,然后通过切片缓冲区移动到下一个数据包。但是我丢失了数据包,因为我在 for 循环上的条件是 buffer.length 并且缓冲区长度正在变化(越来越短)但 i 值总是在增加!有什么想法可以解决这个问题吗?

bufferFragment 用于捕获部分数据包并将它们附加到下一个数据包的开头。这部分有效。

for (var i = 0; i < buffer.length; i++) 
{
    if (buffer[i] == 16 && buffer[i + 1] == 3)
    {
        dataPacket = buffer.slice(0,i+4);
        parseData(dataPacket);
        buffer = buffer.slice(i+4);
    }
    else
    {
        bufferFragment = buffer;
    }
}

更新

似乎在某些情况下,当循环较长时会变得贪婪并捕获比应有的更多数据。

这是一个完整的测试脚本 (http://runnable.com/U75ce4esNHFj7028)

var testBufferText = "100207b097a5085da120f30000461003e39410020736e7bb085d4952890000011003a9401002070c8a1f094ca120f394743e10038907100207a41c22095d4008de0000011003437e1002058e535109a0000a1a9b580000000000a963bf10035c45100207d49681095d4952890000011003827b10020b012447505654472c2c542c2c4d2c302e3130392c4e2c302e3230312c4b2c412a32380d0a10032a621002073e36c3095da120f300004610036e461002072297e7095d49528900000110038c5f1002017866350a8d40622d588135b07db35d000000100305ce1002070c673c0a5da120f30000461003fc331002071c21950a0d5aa29a00fc711003165e10";

var testBuffer = new Buffer(testBufferText,'hex');

var bufferFragment;

extractPackets(testBuffer);

function extractPackets(data) 
{
    var buffer = new Buffer(data);
    var origBuffer = buffer;
    var findCount = 0;

    var startFlag = false;
    var shortenedFlag = 0;
    var appendedData = false;

    if (bufferFragment) 
    {   
        buffer = Buffer.concat([bufferFragment, buffer]);
        concatBuffer = new Buffer(buffer.length);
        buffer.copy(concatBuffer);
        appendedData = bufferFragment;
        bufferFragment = undefined;
    }

    for (var i = 0; i < buffer.length; i++) {
        if (buffer[i] == 16 && buffer[i + 1] == 16) 
        {
            shortenedFlag += 1;
            buffer = Buffer.concat([buffer.slice(0, i), buffer.slice(i + 1)]);
        }
    }

    for (var i = 0; i < buffer.length; i++) {
        //Look for a DLE Packet
        if (buffer[i] == 16)
        {
            if (buffer[i + 1] != 16 && buffer[i + 1] != 3)
            {
                startFlag = true;
                break;
            }
        }
        else
        {
            buffer = buffer.slice(i + 1);
        }
    }

    var sameAsTempBuffer = new Buffer(buffer.length);
    buffer.copy(sameAsTempBuffer);

    // if we detected a start, look for end of packet 10 03
    if(startFlag == true)
    {
        for (var i = 0; i < buffer.length; i++) 
        {
            if (buffer[i] == 16 && buffer[i + 1] == 3)
            {
                var dataPacket = buffer.slice(0,i+4);

                buffer = buffer.slice(i+4);
                i -= 4;

                console.log("Data Packet to Process",dataPacket);
            }

        }
    }

    if (buffer.length)
    {
        bufferFragment = buffer;
    }

    return;
}

输出是

Data Packet to Process <Buffer 10 02 07 b0 97 a5 08 5d a1 20 f3 00 00 46 10 03 e3 94>
Data Packet to Process <Buffer 10 02 07 36 e7 bb 08 5d 49 52 89 00 00 01 10 03 a9 40>
Data Packet to Process <Buffer 10 02 07 0c 8a 1f 09 4c a1 20 f3 94 74 3e 10 03 89 07>
Data Packet to Process <Buffer 10 02 07 a4 1c 22 09 5d 40 08 de 00 00 01 10 03 43 7e>
Data Packet to Process <Buffer 10 02 05 8e 53 51 09 a0 00 0a 1a 9b 58 00 00 00 00 00 a9 63 bf 10 03 5c 45>
Data Packet to Process <Buffer 10 02 07 d4 96 81 09 5d 49 52 89 00 00 01 10 03 82 7b 10 02 0b 01 24 47 50 56 54 47 2c 2c 54 2c 2c 4d 2c 30 2e 31 30 39 2c 4e 2c 30 2e 32 30 31 2c 4b 2c ...>
Data Packet to Process <Buffer 10 02 07 3e 36 c3 09 5d a1 20 f3 00 00 46 10 03 6e 46 10 02 07 22 97 e7 09 5d 49 52 89 00 00 01 10 03 8c 5f 10 02 01 78 66 35 0a 8d 40 62 2d 58 81 35 b0 ...>

前 5 个没问题,然后循环变得贪婪并尝试捕获更多数据包!

【问题讨论】:

  • 在缩短缓冲区时从i 中减去?
  • 不,我不能从 i 中减去,因为它永远不会完成循环,因为它永远不会达到原始的 buffer.length。还有i+4是正确的地方
  • 问题到底出在哪里?我看不出更改.length 会成为问题。我所看到的是您正在处理buffer.slice(0, i+4),它不包括i+4。然后你正在做buffer = buffer.slice(i+4),这会让你找到正确的索引......直到循环执行i++,这会让你跳过一个索引,因此我在上面的建议。
  • 这就是我的意思。 jsfiddle.net/864Sp你的情况有什么不同吗?

标签: javascript node.js loops


【解决方案1】:

居然找到了答案!关键是将 i 添加到偏移量!

var testBufferText = "100207b097a5085da120f30000461003e39410020736e7bb085d4952890000011003a9401002070c8a1f094ca120f394743e10038907100207a41c22095d4008de0000011003437e1002058e535109a0000a1a9b580000000000a963bf10035c45100207d49681095d4952890000011003827b10020b012447505654472c2c542c2c4d2c302e3130392c4e2c302e3230312c4b2c412a32380d0a10032a621002073e36c3095da120f300004610036e461002072297e7095d49528900000110038c5f1002017866350a8d40622d588135b07db35d000000100305ce1002070c673c0a5da120f30000461003fc331002071c21950a0d5aa29a00fc711003165e10";

var testBuffer = new Buffer(testBufferText,'hex');

var bufferFragment;

extractPackets(testBuffer);

function extractPackets(data) 
{
    var buffer = new Buffer(data);
    var origBuffer = buffer;
    var findCount = 0;

    var startFlag = false;
    var shortenedFlag = 0;
    var appendedData = false;

    if (bufferFragment) 
    {   
        buffer = Buffer.concat([bufferFragment, buffer]);
        concatBuffer = new Buffer(buffer.length);
        buffer.copy(concatBuffer);
        appendedData = bufferFragment;
        bufferFragment = undefined;
    }

    for (var i = 0; i < buffer.length; i++) {
        if (buffer[i] == 16 && buffer[i + 1] == 16) 
        {
            shortenedFlag += 1;
            buffer = Buffer.concat([buffer.slice(0, i), buffer.slice(i + 1)]);
        }
    }

    for (var i = 0; i < buffer.length; i++) {
        //Look for a DLE Packet
        if (buffer[i] == 16)
        {
            if (buffer[i + 1] != 16 && buffer[i + 1] != 3)
            {
                startFlag = true;
                break;
            }
        }
        else
        {
            buffer = buffer.slice(i + 1);
        }
    }

    var sameAsTempBuffer = new Buffer(buffer.length);
    buffer.copy(sameAsTempBuffer);

    // if we detected a start, look for end of packet 10 03
    if(startFlag == true)
    {
        for (var i = 0; i < buffer.length; i++) 
        {
            if (buffer[i] == 16 && buffer[i + 1] == 3)
            {
                var dataPacket = buffer.slice(0,i+4);

                buffer = buffer.slice(i+4);
                i -= i + 4;

                console.log("Data Packet to Process",dataPacket);
            }

        }
    }

    if (buffer.length)
    {
        bufferFragment = buffer;
    }

    return;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-07-27
    • 1970-01-01
    • 2023-04-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-02-19
    相关资源
    最近更新 更多