2016-03-03 1 views
1

Bonjour les gars J'ai du mal à comprendre l'ordre des octets réseau et l'ordre dans lequel les données sont envoyées et reçues via UDP. J'utilise C#Envoi de paquets UDP dans le bon Endianness

J'ai une tenue de la structure:

message.start_id   = 0x7777CCCC; 
message.message _id  = 0xBBB67000; 
    more data 

la définition du message a [StructLayout(LayoutKind.Sequential)]

J'ai d'abord convertir la structure à un tableau d'octets en utilisant:

public byte[] StructureToByteArray(object obj) 
{ 
    int len = Marshal.SizeOf(obj); 
    byte[] arr = new byte[len]; 
    IntPtr ptr = Marshal.AllocHGlobal(len); 
    Marshal.StructureToPtr(obj, ptr, true); 
    Marshal.Copy(ptr, arr, 0, len); 
    Marshal.FreeHGlobal(ptr); 
    return arr; 
} 

Et alors je vérifie pour l'endianness:

if (BitConverter.IsLittleEndian) 
{ 
    Array.Reverse(packet); 
} 

puis-je l'envoyer

socket.SendTo(packet, endPoint); 

Quand j'envoie ce la réception reçoit le message avec le boutisme correct appliqué, mais les octets dans l'ordre inverse, en regardant si dans Wireshark je reçois:

le reste. ................. BBB67000 7777CCCC

quand j'attends: 7777CCCC BBB67000 ................... .le reste

Est ce que je m'attends à droite ou est-ce normal que le premier octet dans le st la structure est la dernière à arriver?

Merci beaucoup

+2

L'endianness ne devrait pas être appliqué sur l'ensemble du paquet - il devrait être appliqué sur les parties individuelles ... Je pense que c'est sur tous les 32 bits, mais je ne suis pas à 100% sur ce point. –

+1

Presque ce que Michael Bray a dit. Endianness est appliqué sur les parties individuelles (donc séparément pour 'start_id' et' message_id'), et il est au niveau de l'octet (donc dans un int de 4 octets, le 1er avec le 4ème octet sont échangés, et le 2ème avec le 3ème) – xanatos

Répondre

3

Je vais avoir l'ordre des octets réseau du mal à comprendre et l'ordre dans lequel les données sont envoyées et reçues sur UDP

Les données sont envoyées et reçues sur UDP exactement l'octet ordre donné à la prise. Vous envoyez ou recevez uniquement des tableaux d'octets et UDP ne réorganise pas les octets dans un datagramme du tout.

Alors, la question est: que faire de l'endianisme?

Eh bien, dans de nombreux cas, la réponse est "rien". Pour commencer, la plupart des ordinateurs que vous rencontrerez aujourd'hui utilisent l'architecture x86 et utilisent toujours little-endian. Et dans de nombreux cas, vous avez le contrôle sur les deux extrémités de toute façon et vous pouvez toujours rester avec l'un ou l'autre. Si votre API a un moyen de convertir des objets vers et à partir de flux d'octets, vous pouvez simplement le faire et envoyer et recevoir ces octets directement avec votre socket UDP. Mais oui, parfois, vous devez être en mesure de gérer la transmission de données dans une endianness différente de celle supportée nativement sur l'architecture sur laquelle votre programme est en cours d'exécution. Dans votre exemple particulier, vous semblez avoir choisi d'utiliser big-endian comme ordre des octets pour votre protocole (je déduis cela du peu de code & hellip, ce n'est pas vraiment possible de savoir avec certitude a good Minimal, Complete, and Verifiable example) . Ce qui est bien; l'API de socket BSD d'origine inclut le concept de «l'ordre des octets du réseau», qui est big-endian. La bibliothèque de socket inclut des fonctions à convertir, par ex. Les entiers de 16 bits de "l'ordre d'hôte" à "l'ordre de réseau" et en arrière.

Mais il est important de comprendre que l'endianness affecte vos données au niveau de chaque primitive individuelle dans vos données.Vous ne pouvez pas inverser tout le tableau d'octets en même temps, car si vous le faites, cela changera non seulement l'endianisme de chaque primitive, mais aussi l'ordre des primitives elles-mêmes. Et bien sûr, vous voyez cela dans votre trace Wireshark: les deux champs dans votre structure de données ont vu leur commande permutée.

Pour gérer l'endianness correctement, vous devez parcourir chaque champ de votre structure de données et échanger les octets individuellement. Vous laisserez les octets seuls, short les valeurs (16 bits) auront leur paire d'octets permutés, int les valeurs (32 bits) auront leur séquence de quatre octets inversée, long les valeurs (64 bits) auront huit octets inversés, et ainsi de suite. Pour compliquer les choses, certaines structures de données ne sont pas du tout affectées par l'endianness (par exemple le texte codé UTF8), alors que d'autres ont des règles plus complexes (par exemple un GUID/UUID de Windows, qui est une valeur de 128 bits). c'est en fait défini comme une structure de données complexe, ayant plusieurs champs de taille variable). La chose importante à retenir est que l'endianness est toujours appliqué au niveau de chaque valeur de données primitive, en tenant compte du nombre réel d'octets utilisés par la valeur de données primitive.

+0

Salut Peter, Merci beaucoup pour votre réponse. J'ai jeté un coup d'œil aux différentes fonctions MS fournies (htonl etc.) mais je n'ai rien trouvé pour les uints, les doubles etc. J'ai un mélange de tout dans la structure que j'avais besoin d'envoyer. comme toutes les valeurs sont 32 bits, j'ai inversé manuellement les octets dans la structure des octets en itérant à travers la structure 1 octet à temps, copiant dans un nouvel octet, effectuant un tableau.Reverse et copiant cela dans une nouvelle structure d'octets de la même taille . Je l'ai testé sur le fil et il semble fonctionner: \. Merci beaucoup. – moonraker