0

私はシリアル通信プロトコルに取り組んでいます。このプロトコルでは、packt はバイトで構成され、先頭と末尾は0x7E.

プロトコルは、エスケープする、または0x7Eエスケープ0x7Dする必要がある任意のバイトを示します。0x7D 0x5E0x7d 0x5D

サンプルパケットは次のとおりです。

7E 40 09 00 BE EF 05 7E 06 01 02 03 04 05 7E

ご覧のとおりbyte[7]、このパケットでは 2 バイトに置き換える必要があります0x7D 0x5E。これに対して、私は以下の方法を書きましたが、このタスクを実行できません:

private List<byte> Finalize(List<byte> packet)
{
    int u = 1; //keep track of end of pack
    //because if escape characters are present
    //end bit will be shifted to right

    //Walk through list and fix escape bytes
    for (int i = 1; i < packet.Count; i++)
    {
        if (packet[i] == 0x7D)
        {
            packet[u] = 0x7D;
            packet[u + 1] = 0x5D;
            u += 2;
        }
        else if (packet[i] == 0x7E) //Sync Byte
        {
            packet[u] = 0x7D;
            packet[u + 1] = 0x5E;
            u += 2;
        }
        else
        {
           packet[u] = packet[i]; //Exception here!!
           u++;
        }
    }

    return packet;
}

メソッドはArgumentOutOfRangeException. 誰かが何が問題なのか教えてもらえますか!? 正しいロジックを実装したと思いますが、インデックスを適切に処理していないようです!

ループはインデックス 1 から開始しています。これは開始バイトであり、変更すべきではないためです。また、リストの最後のバイトである 0x7E (最後のバイト) も変更しないでください。

4

4 に答える 4

2

新しいリストを作成し、元のリストから新しいリストにデータをコピーすることをお勧めします。「その場で」更新を行う方法はあるかもしれませんが、新しいリストを単純に作成する方がおそらく簡単です。実際には、新しい配列を作成する前に、元の配列内の 7D または 7E 文字の数をカウントする必要がありますが、byte[]むしろa を使用するList<byte>方がよい場合があります。

于 2012-10-16T23:21:08.150 に答える
1

これは、パケットをエスケープする拡張メソッドです。デフォルトである最初と最後のバイトには触れません。

public static IEnumerable<byte> Finalize(this IList<byte> packet)
{
    yield return 0x7E;

    for(int i = 1; i < packet.Count - 1; i++)
    {
        if (packet[i] == 0x7E)
        {
            yield return 0x7D;
            yield return 0x5E;
            continue;
        }

        if (packet[i] == 0x7D)
        {
            yield return 0x7D;
            yield return 0x5D;
            continue;
        }

        yield return packet[i];
    }

    yield return 0x7E;
}

使い方は簡単です:

byte[] packet = { 0x7E, 0x40, 0x09, 0xEF, 0x05, 0x7E, 0x06, 0x04, 0x05, 0x7E };
byte[] escapedPacket = packet.Finalize().ToArray();
于 2012-10-17T00:20:24.470 に答える
1

まず、バイトの隣のバイトを値 0x7Dとで上書きすると、データが失われます0x7E。第二に、言及された例外を生成するuよりも速く変更しています。iバイトをエスケープすると、 に 2 が追加uされますが、そのループの反復ではfor、 i がインクリメントされるだけです。第三に、これに対するより良いアプローチは間違いなく while ループです。

最初の問題を処理するには、リストにさらに要素を追加する必要があります。Insertすべてを手動で右にシフトする代わりに、トリックを実行します。2 つ目の問題は、カウンターを 1 つだけ使用することで解決できます。コードを確認してください:

        private List<byte> Finalize(List<byte> packet)
        {
            int i = 1;
            while (i < packet.Count-1)
            {
                if (packet[i] == 0x7D)
                {
                    packet[i] = 0x7D;
                    packet.Insert(i+1, 0x5D);
                    i += 2;
                }
                else if (packet[i] == 0x7E) //Sync Byte
                {
                    packet[i] = 0x7D;
                    packet.Insert(i+1, 0x5E);
                    i += 2;
                }
                else 
                    i++;
            }
            return packet;
       }

もう 1 つの解決策は、メソッド内に新しいリストを作成し、それに適切な値を追加することです。 while (i < packet.Count-1)最後のバイトをエスケープしたくないと思うからです。packet[packet.Count-1]リストの最後のバイトはそうではないことに注意してくださいpacket[packet.Count]

于 2012-10-16T23:38:52.273 に答える
0

私はC#に精通していませんが、ソースパケットを上書きしているようで、途中で破損しているようです。

また、リストは自動的に成長しますか? 長さを超えて書いているからです。リストはそれをどのように処理しますか?

ループは 1 または 0 から開始する必要がありますか? 終了条件は「i <= packet.Count」ではなく「i <= packet.Count」であるため、最後のバイトが欠落します。

于 2012-10-16T23:29:40.223 に答える