67

UDP/IP 経由で制御できるハードウェアのドキュメントで、次のフラグメントを見つけました。

この通信プロトコルでは、DWORD は 4 バイトのデータ、WORD は 2 バイトのデータ、BYTE は 1 バイトのデータです。格納形式はリトル エンディアンです。つまり、4 バイト (32 ビット) のデータは、d7-d0、d15-d8、d23-d16、d31-d24 として格納されます。2 バイト (16 ビット) のデータは、d7-d0 、d15-d8 として格納されます。

これが C# にどのように変換されるのか疑問に思っています。送信する前にデータを変換する必要がありますか? たとえば、32 ビット整数または 4 文字の文字列を送信したい場合は?

4

6 に答える 6

90

C#自体はエンディアンを定義しません。ただし、バイトに変換するときはいつでも、選択を行っています。BitConverterクラスにはIsLittleEndianフィールドがあり、それがどのように動作するかを示しますが、選択肢はありません。同じことがBinaryReader/BinaryWriterにも当てはまります。

私のMiscUtilライブラリには、エンディアンを定義できるEndianBitConverterクラスがあります。BinaryReader/Writerにも同様の同等物があります。私が恐れているオンライン使用ガイドはありませんが、それらは些細なことです:)

(EndianBitConverterには、通常のBitConverterにはない機能もあります。これは、バイト配列のインプレースで変換を行うためのものです。)

于 2008-10-20T10:21:02.873 に答える
48

使用することもできます

IPAddress.NetworkToHostOrder(...)

短い、intまたは長い。

于 2008-10-20T10:29:58.817 に答える
12

リトルエンディアンに関して、短い答え(何かをする必要がある)は「おそらくそうではありませんが、ハードウェアによって異なります」です。次の方法で確認できます。

bool le = BitConverter.IsLittleEndian;

これが何を言っているのかによっては、バッファの一部を逆にしたいかもしれません。あるいは、Jon Skeet が特定のエンディアン コンバーターを提供しています(EndianBitConverter を探してください)。

Itanium (たとえば) はビッグエンディアンであることに注意してください。ほとんどの Intel はリトルエンディアンです。

特定のUDP / IPについて...?

于 2008-10-20T10:20:04.530 に答える
3

ネットワークのバイト順序とCPUエンディアンについて知る必要があります。

通常、TCP / UDP通信の場合、htons関数(およびntohs、およびそれらに関連する関数)を使用して、常にデータをネットワークバイトオーダーに変換します。

通常、ネットワークの順序はビッグエンディアンですが、この場合(何らかの理由で!)通信はリトルエンディアンであるため、これらの関数はあまり役に立ちません。実装したUDP通信が他の標準に従っていると想定できないため、これは重要です。また、ビッグエンディアンアーキテクチャを使用している場合は、すべてを適切にラップできないため、作業が困難になりhtonsます:-(

ただし、Intel x86アーキテクチャを使用している場合は、すでにリトルエンディアンであるため、変換せずにデータを送信するだけです。

于 2008-10-20T10:25:30.027 に答える
1

UDP マルチキャストでパックされたデータをいじっていますが、パケット ヘッダー (Wireshark) のエラーに気付いたので、UInt16 オクテットを並べ替えるために何かが必要だったので、これを作成しました。

    private UInt16 swapOctetsUInt16(UInt16 toSwap)
    {
        Int32 tmp = 0;
        tmp = toSwap >> 8;
        tmp = tmp | ((toSwap & 0xff) << 8);
        return (UInt16) tmp;
    }

UInt32の場合、

    private UInt32 swapOctetsUInt32(UInt32 toSwap)
    {
        UInt32 tmp = 0;
        tmp = toSwap >> 24;
        tmp = tmp | ((toSwap & 0xff0000) >> 8);
        tmp = tmp | ((toSwap & 0xff00) << 8);
        tmp = tmp | ((toSwap & 0xff) << 24);
        return tmp;
    }

これはテスト用です

    private void testSwap() {
        UInt16 tmp1 = 0x0a0b;
        UInt32 tmp2 = 0x0a0b0c0d;
        SoapHexBinary shb1 = new SoapHexBinary(BitConverter.GetBytes(tmp1));
        SoapHexBinary shb2 = new SoapHexBinary(BitConverter.GetBytes(swapOctetsUInt16(tmp1)));
        Debug.WriteLine("{0}", shb1.ToString());
        Debug.WriteLine("{0}", shb2.ToString());
        SoapHexBinary shb3 = new SoapHexBinary(BitConverter.GetBytes(tmp2));
        SoapHexBinary shb4 = new SoapHexBinary(BitConverter.GetBytes(swapOctetsUInt32(tmp2)));
        Debug.WriteLine("{0}", shb3.ToString());
        Debug.WriteLine("{0}", shb4.ToString());
    }

出力元は次のとおりです。

    0B0A: {0}
    0A0B: {0}
    0D0C0B0A: {0}
    0A0B0C0D: {0}
于 2015-09-10T20:25:11.107 に答える
0

解析していてパフォーマンスが重要でない場合は、次の非常に単純なコードを検討してください。

private static byte[] NetworkToHostOrder (byte[] array, int offset, int length)
{
    return array.Skip (offset).Take (length).Reverse ().ToArray ();
}

int foo = BitConverter.ToInt64 (NetworkToHostOrder (queue, 14, 8), 0);
于 2012-11-08T10:38:59.210 に答える