Pregunta

En la documentación de hardware que nos permite controlarlo a través de UDP / IP, Encontré el siguiente fragmento:

  

En este protocolo de comunicación, DWORD es un dato de 4 bytes, WORD es un dato de 2 bytes,   BYTE es un byte de datos único. El formato de almacenamiento es little endian, es decir, los datos de 4 bytes (32 bits) se almacenan como: d7-d0, d15-d8, d23-d16, d31-d24; los datos de bytes dobles (16 bits) se almacenan como: d7-d0, d15-d8.

Me pregunto cómo se traduce esto a C #. ¿Tengo que convertir cosas antes de enviarlo? Por ejemplo, si quiero enviar un entero de 32 bits o una cadena de 4 caracteres?

¿Fue útil?

Solución

C # en sí no define la endianidad. Sin embargo, siempre que conviertes a bytes, estás haciendo una elección. La clase BitConverter tiene una IsLittleEndian para decirle cómo se comportará, pero no le da la opción. Lo mismo ocurre con BinaryReader / BinaryWriter.

Mi MiscUtil tiene una clase EndianBitConverter que le permite definir la endianness; hay equivalentes similares para BinaryReader / Writer. No tengo una guía de uso en línea, me temo, pero son triviales :)

(EndianBitConverter también tiene una funcionalidad que no está presente en el BitConverter normal, que es hacer conversiones in situ en una matriz de bytes).

Otros consejos

También puedes usar

IPAddress.NetworkToHostOrder(...)

Para abreviar, int o long.

Re little-endian, la respuesta corta (para hacer tengo que hacer algo) es "probablemente no, pero depende de su hardware". Puedes consultar con:

bool le = BitConverter.IsLittleEndian;

Dependiendo de lo que esto diga, es posible que desee invertir partes de sus memorias intermedias. Alternativamente, Jon Skeet tiene convertidores endian específicos aquí (busque EndianBitConverter).

Tenga en cuenta que los itanios (por ejemplo) son big-endian. La mayoría de los Intels son little-endian.

Re el UDP / IP específico ...?

Necesita saber sobre el orden de bytes de la red así como también sobre la capacidad de la CPU.

Por lo general, para las comunicaciones TCP / UDP, siempre se convierten los datos al orden de bytes de la red utilizando Función htons (y ntohs , y sus funciones relacionadas).

Normalmente, el orden de la red es big-endian, pero en este caso (¡por alguna razón!) la comunicación es little endian, por lo que esas funciones no son muy útiles. Esto es importante ya que no puede asumir que las comunicaciones UDP que han implementado siguen otros estándares, también dificulta la vida si tiene una arquitectura big endian ya que simplemente no puede envolver todo con htons como usted debería :-(

Sin embargo, si viene de una arquitectura Intel x86, entonces ya es little-endian, así que simplemente envíe los datos sin conversión.

Si está analizando y el rendimiento no es crítico, considere este código muy simple:

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

Estoy jugando con datos empaquetados en UDP Multicast y necesitaba algo para reordenar los octetos UInt16 ya que noté un error en el encabezado del paquete (Wireshark), así que hice esto:

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

En el 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;
    }

Esto es solo para pruebas

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

de donde salió esta salida:

    0B0A: {0}
    0A0B: {0}
    0D0C0B0A: {0}
    0A0B0C0D: {0}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top