Domanda

Nella documentazione dell'hardware che ci consente di controllarlo tramite UDP / IP, Ho trovato il seguente frammento:

  

In questo protocollo di comunicazione, DWORD è un dato di 4 byte, WORD è un dato di 2 byte,   BYTE è un dato a byte singolo. Il formato di archiviazione è little endian, ovvero i dati a 4 byte (32 bit) sono memorizzati come: d7-d0, d15-d8, d23-d16, d31-d24; i dati a doppio byte (16 bit) sono memorizzati come: d7-d0, d15-d8.

Mi chiedo come questo si traduca in C #? Devo convertire materiale prima di inviarlo? Ad esempio, se voglio inviare un numero intero a 32 bit o una stringa di 4 caratteri?

È stato utile?

Soluzione

C # stesso non definisce l'endianness. Ogni volta che ti converti in byte, tuttavia, stai facendo una scelta. La classe BitConverter ha una IsLittleEndian per dirti come si comporterà, ma non ti dà la scelta. Lo stesso vale per BinaryReader / BinaryWriter.

La mia MiscUtil ha una classe EndianBitConverter che ti permette di definire l'endianness; esistono equivalenti simili per BinaryReader / Writer. Nessuna guida all'uso online temo, ma sono banali :)

(EndianBitConverter ha anche una funzionalità che non è presente nel normale BitConverter, che consiste nel fare conversioni sul posto in un array di byte.)

Altri suggerimenti

Puoi anche usare

IPAddress.NetworkToHostOrder(...)

In breve, int o long.

Re little-endian, la risposta breve (per fare devo fare qualsiasi cosa) è "probabilmente no, ma dipende dal tuo hardware". Puoi verificare con:

bool le = BitConverter.IsLittleEndian;

A seconda di ciò che dice, potresti voler invertire parti dei tuoi buffer. In alternativa, Jon Skeet ha convertitori endian specifici qui (cercare EndianBitConverter).

Nota che gli itani (per esempio) sono big-endian. La maggior parte degli Intel sono little-endian.

Riguardo allo specifico UDP / IP ...?

È necessario conoscere l'ordine dei byte di rete e l'endianità della CPU.

In genere per le comunicazioni TCP / UDP, si convertono sempre i dati in ordine di byte di rete utilizzando htons (e ntohs e le relative funzioni).

Normalmente l'ordine di rete è big-endian, ma in questo caso (per qualche motivo!) la comunicazione è little endian, quindi quelle funzioni non sono molto utili. Questo è importante poiché non puoi presumere che le comunicazioni UDP che hanno implementato seguano altri standard, inoltre rende la vita difficile se hai un'architettura big-endian in quanto non puoi semplicemente avvolgere tutto con htons come te dovrebbe :-(

Tuttavia, se provenite da un'architettura Intel x86, allora siete già little-endian, quindi inviate semplicemente i dati senza conversione.

Se stai analizzando e le prestazioni non sono fondamentali, considera questo codice molto semplice:

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

Sto giocando con i dati compressi in UDP Multicast e avevo bisogno di qualcosa per riordinare gli ottetti UInt16 poiché ho notato un errore nell'intestazione del pacchetto (Wireshark), quindi ho fatto questo:

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

Nel caso di 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;
    }

Questo è solo per il test

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

da cui l'output è stato questo:

    0B0A: {0}
    0A0B: {0}
    0D0C0B0A: {0}
    0A0B0C0D: {0}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top