programing

C # 리틀 엔디안 또는 빅 엔디안?

nasanasas 2020. 11. 30. 17:55
반응형

C # 리틀 엔디안 또는 빅 엔디안?


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 자 문자열을 통해 전송하려면?


C # 자체는 엔디안을 정의하지 않습니다. 그러나 바이트로 변환 할 때마다 선택하는 것입니다. BitConverter의 클래스는이 IsLittleEndian 가 동작하는 방법을 알려줄 필드를하지만 선택의 여지를 제공하지 않습니다. BinaryReader / BinaryWriter도 마찬가지입니다.

MiscUtil 라이브러리에는 엔디안을 정의 할 수있는 EndianBitConverter 클래스가 있습니다. BinaryReader / Writer에 대한 유사한 항목이 있습니다. 온라인 사용 가이드는 없지만 사소한 것 같습니다. :)

(EndianBitConverter에는 일반 BitConverter에는없는 기능이 있는데, 이는 바이트 배열에서 제자리에서 변환을 수행하는 것입니다.)


당신은 또한 사용할 수 있습니다

IPAddress.NetworkToHostOrder(...)

short, int 또는 long.


리틀 엔디안의 경우 짧은 대답 (내가해야 할 일이 무엇이든해야 함)은 "아마도 아니 겠지만 하드웨어에 따라 다릅니다"입니다. 다음으로 확인할 수 있습니다.

bool le = BitConverter.IsLittleEndian;

이것이 말하는 내용에 따라 버퍼의 일부를 반전시킬 수 있습니다. 또는 Jon Skeet에는 여기에 특정 엔디안 변환기가 있습니다 (EndianBitConverter 검색).

아이테니엄 (예 :)은 빅 엔디안입니다. 대부분의 인텔은 리틀 엔디안입니다.

특정 UDP / IP ...?


네트워크 바이트 순서와 CPU 엔디안에 대해 알아야합니다.

일반적으로 TCP / UDP 통신의 경우 항상 htons함수 (및 ntohs및 관련 함수)를 사용하여 데이터를 네트워크 바이트 순서로 변환합니다 .

일반적으로 네트워크 순서는 빅 엔디안이지만이 경우 (어떤 이유로!) 통신은 리틀 엔디안이므로 이러한 기능은 그다지 유용하지 않습니다. 이는 그들이 구현 한 UDP 통신이 다른 표준을 따르고 있다고 가정 할 수 없기 때문에 중요하며, 모든 것을 원하는 htons대로 래핑 할 수 없기 때문에 빅 엔디안 아키텍처를 사용하는 경우 삶을 어렵게 만듭니다.

그러나 인텔 x86 아키텍처에서 온다면 이미 리틀 엔디안이므로 변환하지 않고 데이터를 보내십시오.


구문 분석 중이고 성능이 중요하지 않은 경우 다음 매우 간단한 코드를 고려하십시오.

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);

UDP Multicast에서 압축 된 데이터를 가지고 놀고 있는데 패킷 헤더 (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());
    }

from which output was this:

    0B0A: {0}
    0A0B: {0}
    0D0C0B0A: {0}
    0A0B0C0D: {0}

참고URL : https://stackoverflow.com/questions/217980/c-sharp-little-endian-or-big-endian

반응형