toint32 bytes c# hardware udp endianness

c# - bytes - byte[] to int



C#little endian o big endian? (6)

C # en sí mismo no define la endianidad. Sin embargo, cuando convierte a bytes, está haciendo una elección. La clase BitConverter tiene un campo IsLittleEndian para decirle cómo se comportará, pero no da la opción. Lo mismo aplica para BinaryReader / BinaryWriter.

Mi biblioteca MiscUtil tiene una clase EndianBitConverter que te permite definir el endianness; hay equivalentes similares para BinaryReader / Writer. Ninguna 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 consiste en realizar conversiones in situ en una matriz de bytes).

En la documentación del 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 dato de un solo byte. El formato de almacenamiento es poco endian, es decir, los datos de 4 bytes (32 bits) se almacenan como: d7-d0, d15-d8, d23-d16, d31-d24; los datos de doble byte (16bits) se almacenan como: d7-d0, d15-d8.

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


Debe conocer el orden de los bytes de la red y la permanencia de la CPU.

Normalmente, para las comunicaciones TCP / UDP, siempre convierte los datos en orden de bytes de red usando la 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!) Las comunicaciones son poco endian, por lo que esas funciones no son muy útiles. Esto es importante ya que no puede suponer que las comunicaciones UDP que han implementado siguen otros estándares, sino que también dificulta la vida si tiene una arquitectura big-endian, ya que no puede envolver todo con htons como debería :-(

Sin embargo, si vienes de una arquitectura Intel x86, entonces ya eres un pequeño endian, así que solo envía los datos sin conversión.


Estoy jugando con datos empaquetados en UDP Multicast y necesitaba algo para reordenar 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 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 probar

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ó esto:

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


Re little-endian, la respuesta corta (para hacer lo que necesito hacer) es "probablemente no, pero depende de tu hardware". Puede consultar con:

bool le = BitConverter.IsLittleEndian;

Dependiendo de lo que diga, es posible que desee invertir partes de sus búferes. Alternativamente, Jon Skeet tiene convertidores Endian específicos here (busque EndianBitConverter).

Tenga en cuenta que los itaniums (por ejemplo) son big-endian. La mayoría de los intels son pequeños endian.

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


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


También puedes usar

IPAddress.NetworkToHostOrder(...)

Para abreviar, int o largo.