Question

Dans la documentation du matériel qui nous permet de le contrôler via UDP / IP, J'ai trouvé le fragment suivant:

  

Dans ce protocole de communication, DWORD est une donnée de 4 octets, WORD est une donnée de 2 octets,   BYTE est une donnée à un octet. Le format de stockage est little endian, à savoir 4 octets (32bits). Les données sont stockées comme suit: d7-d0, d15-d8, d23-d16, d31-d24; les données sur deux octets (16 bits) sont stockées comme suit: d7-d0, d15-d8.

Je me demande comment cela se traduit en C #? Dois-je convertir des documents avant de les envoyer? Par exemple, si je veux envoyer un entier 32 bits ou une chaîne de 4 caractères?

Était-ce utile?

La solution

C # lui-même ne définit pas l’endianisme. Cependant, chaque fois que vous convertissez en octets, vous faites un choix. La classe BitConverter a un IsLittleEndian pour vous indiquer comment il va se comporter, mais ne donne pas le choix. Il en va de même pour BinaryReader / BinaryWriter.

Ma bibliothèque MiscUtil possède une classe EndianBitConverter qui vous permet de définir le caractère final. il existe des équivalents similaires pour BinaryReader / Writer. Je crains fort, il n’existe pas de guide d’utilisation en ligne:

(EndianBitConverter possède également une fonctionnalité qui n'est pas présente dans BitConverter normal, qui consiste à effectuer des conversions sur place dans un tableau d'octets.)

Autres conseils

Vous pouvez également utiliser

IPAddress.NetworkToHostOrder(...)

Pour court, int ou long.

Petit-endian, la réponse courte (je dois faire quoi que ce soit) est "probablement pas, mais cela dépend de votre matériel". Vous pouvez vérifier avec:

bool le = BitConverter.IsLittleEndian;

En fonction de ce que cela dit, vous voudrez peut-être inverser des parties de vos tampons. Jon Skeet propose également des convertisseurs spécifiques (recherchez EndianBitConverter).

Notez que les itaniums (par exemple) sont big-endian. La plupart des Intels sont little-endian.

Concernant le protocole UDP / IP spécifique??

Vous devez connaître l'ordre des octets du réseau ainsi que l'état du processeur.

Généralement, pour les communications TCP / UDP, vous convertissez toujours les données en ordre d'octet réseau à l'aide de htons fonction (et ntohs et leurs fonctions connexes).

Normalement, l'ordre du réseau est big-endian, mais dans ce cas (pour une raison quelconque!), les communications sont peu endianes, donc ces fonctions ne sont pas très utiles. Ceci est important car vous ne pouvez pas supposer que les communications UDP qu’ils ont implémentées sont conformes à d’autres normes. Cela rend également la vie difficile si vous avez une architecture big-endian, car vous ne pouvez pas tout encapsuler avec htons . devrait: - (

Cependant, si vous venez d'une architecture Intel x86, vous êtes déjà un peu endianiste, envoyez simplement les données sans conversion.

Si vous analysez et que les performances ne sont pas critiques, considérez ce code très 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);

Je m'amuse avec des données compactes dans UDP Multicast et j'avais besoin de quelque chose pour réorganiser les octets UInt16 car j'avais remarqué une erreur dans l'en-tête du paquet (Wireshark). J'ai donc fait ceci:

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

Dans le cas 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;
    }

Ceci est juste pour tester

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

à partir de quelle sortie était ceci:

    0B0A: {0}
    0A0B: {0}
    0D0C0B0A: {0}
    0A0B0C0D: {0}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top