Pergunta

Na documentação de hardware que nos permite controlá-lo via UDP / IP, Eu encontrei o seguinte fragmento:

Neste protocolo de comunicação, DWORD é um 4 bytes de dados, palavra é um dois bytes de dados, BYTE é um único byte de dados. O formato de armazenamento é pouco endian, nomeadamente quatro bytes (32bits) os dados são armazenados como: D7-D0, D15-D8, D23-D16, D31-D24; bytes duplas (16 bits) de dados é armazenado como:. D7-D0, D15-D8

Eu estou querendo saber como isso se traduz em C #? Eu tenho que converter material antes de enviá-los? Por exemplo, se eu quiser enviar mais de um inteiro de 32 bits ou uma string de 4 caracteres?

Foi útil?

Solução

C si # não define o endianness. Sempre que você converter para bytes, no entanto, você está fazendo uma escolha. A BitConverter classe tem um campo IsLittleEndian para lhe dizer como ele vai se comportar, mas não dá a escolha. O mesmo vale para BinaryReader / BinaryWriter.

MiscUtil biblioteca tem uma classe EndianBitConverter que lhe permite definir a ordenação; existem equivalentes semelhantes para BinaryReader / gravador. Nenhum guia de utilização on-line eu tenho medo, mas eles são trivial:)

(EndianBitConverter também tem um pedaço de funcionalidade que não está presente no BitConverter normal, o que é para fazer conversões no local em uma matriz de bytes.)

Outras dicas

Você também pode usar

IPAddress.NetworkToHostOrder(...)

Para short, int ou longo prazo.

Re little-endian, a resposta curta (para fazer o que preciso fazer qualquer coisa) é "provavelmente não, mas isso depende do seu hardware". Você pode verificar com:

bool le = BitConverter.IsLittleEndian;

Dependendo do que este diz, você pode querer reverter porções de seus buffers. Alternativamente, Jon Skeet tem específico-endian conversores aqui (olhar para EndianBitConverter).

Note que itaniums (por exemplo) são big-endian. A maioria da Intel são little-endian.

Re específico UDP / IP ...?

Você precisa saber sobre a ordem de bytes da rede, bem como CPU endian-ness.

Normalmente, para comms TCP / UDP, você sempre converter dados para byte order rede usando o htons função (e ntohs, e as suas funções relacionadas).

ordem de rede Normalmente é big-endian, mas neste caso (por alguma razão!) Os comms é little endian, então essas funções não são muito úteis. Isto é importante porque você não pode assumir o UDP comms eles implementaram acompanhar quaisquer outras normas, mas também torna a vida difícil se você tem uma arquitetura big-endian como você simplesmente não pode embrulhar tudo com htons como você deve: - (

No entanto, se você está vindo de uma arquitetura Intel x86, então você já está little-endian, portanto, basta enviar os dados sem conversão.

Se você é análise e performance não é crítica, considere este código muito simples:

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

Eu estou brincando com dados embalados em UDP Multicast e eu precisava de algo para reordenar octetos UINT16 desde que eu notei um erro no cabeçalho do pacote (Wireshark), então eu fiz o seguinte:

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

Em caso de 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;
    }

Este é apenas para testar

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

a partir do qual a saída era a seguinte:

    0B0A: {0}
    0A0B: {0}
    0D0C0B0A: {0}
    0A0B0C0D: {0}
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top