web-dev-qa-db-fra.com

Puis-je ignorer l'ordre des octets en toute sécurité dans le réseau?

Je développe une application serveur-client où le client fonctionnera sous Windows et le serveur probablement sous Linux. Peut-être que je porterai plus tard le client sur Mac et Linux, mais pas encore.

Tous les ordinateurs personnels fonctionnent de nos jours sur le petit-boutien. J'ai googlé un moment, mais je n'ai pas vraiment pu trouver une liste d'appareils fonctionnant sur big-endian. Pour autant que je sache, certaines puces Motorola utilisent encore du big-endian et peut-être certains téléphones (je ne prévois pas de porter l'application sur les smartphones, donc cela n'a pas d'importance pour moi). Alors, pourquoi réorganiserais-je les octets de chaque entier, chaque court, chaque flottant, double, etc., pour lire et écrire , alors que j'ai déjà savoir que le serveur et le client fonctionnent sur little-endian?

C'est juste un travail inutile à faire. Donc, ma question est: puis-je ignorer l'endianité en toute sécurité et envoyer simplement des données de petit endian? Quels sont les inconvénients?

23
tkausl

... pourquoi devrais-je réorganiser les octets ... alors que je sais déjà que le serveur et le client fonctionnent sur le petit endian? C'est juste un travail inutile à faire.

Ce n'est inutile que si vous pouvez garantir que votre code fonctionnera toujours sur des architectures peu endiennes. Si vous prévoyez qu'il ait une longue durée de vie, cela vaut la peine de faire l'effort supplémentaire pour éviter de perturber le code éprouvé dans une décennie à partir de ce moment où une architecture big-endian est devenue le "in" et que vous trouvez que c'est un bon marché pour ton application.

Il existe un ordre d'octets standard du réseau. C'est du big-endian, mais rien ne dit que vous devez le respecter lors de la conception de votre protocole. Si vous savez à l'avance que la majorité des systèmes exécutant votre code seront peu endiens et que les performances sont critiques, déclarez que le "tkausl standard byte ordering" et allez-y. Où vous appelez normalement htons() pour mettre les choses dans l'ordre dont vous avez besoin, écrivez une macro appelée htots() qui se compile conditionnellement sur rien sur les architectures little-endian et fait la réorganisation sur big-endian.

Maintenir le code pour effectuer les conversions entrantes et sortantes n'est pas vraiment un gros effort. Si vous avez un très grand nombre de messages, trouvez un moyen de les exprimer et écrivez un programme pour générer les conversions entrantes et sortantes.

29
Blrfl

C'est ton protocole.

Vous ne pouvez pas l'ignorer en toute sécurité. Mais vous pouvez l'étiqueter en toute sécurité. Vous contrôlez le client et le serveur. Vous contrôlez le protocole. N'est-il pas logique de ne pas se soucier de savoir si c'est du big-endian ou du little-endian tant que vous savez si les deux parties sont d'accord?

Cela signifie des frais généraux. Maintenant, vous devez marquer votre endianité d'une manière ou d'une autre. Faites cela, et je peux le lire sur n'importe quoi.

Si vous ne voulez pas de surcharge de données et que votre CPU s'ennuie et cherche quelque chose à faire, alors conforme.

7
candied_orange

Donc, ma question est: Puis-je ignorer en toute sécurité l'endianess et envoyer simplement des données little-endian?

Il y a deux interprétations de cela:

  • Si vous concevez vos applications/protocoles pour toujours1 envoyez little-endian, alors vous n'ignorez pas l'endianess.

  • Si vous concevez vos applications/protocoles pour envoyer/recevoir quel que soit l'endianisme natif, alors ils fonctionneront tant que vous exécuterez vos applications sur des plates-formes avec le même endianess natif.

    Est-ce "sûr"2? A vous de juger! Mais il existe certainement des plates-formes matérielles communes qui utilisent le petit-boutien, le gros-boutien ou ... le bi-boutien.

    Référence:

Quels sont les inconvénients?

L'inconvénient évident d'ignorer l'endianess est que si vous/vos utilisateurs devez exécuter vos applications/protocoles entre des plates-formes avec une endianess native différente, alors vous avez un problème. Les applications s'arrêteront et vous devrez les modifier pour résoudre le problème. Et gérer les problèmes de compatibilité des versions, etc.

De toute évidence, la plupart des plates-formes de génération actuelles sont nativement peu endiennes, mais 1) certaines ne le sont pas et 2) nous ne pouvons que deviner ce qui se passera à l'avenir.


1 - Toujours ... y compris sur des plateformes nativement big-endian.

2 - En effet, que signifie "sûr"? Si vous nous demandez de prédire l'orientation future des plates-formes matérielles ... Je crains que ce ne soit pas objectivement responsable.

6
Stephen C

La pile de mise en réseau BSD standard en C a la fonctionnalité hton/ntoh (network-to-Host/Host-to-network) qui s'étendent à no-ops sur des machines natives du réseau (big endian). Vous auriez besoin de vos propres homologues pour ceux-ci pour le scénario dans lequel l'ordre des octets natif du réseau est peu endian.

C'est la manière robuste de le faire.

Ce ne serait pas conventionnel, mais je n'y vois rien de mal. Les ordinateurs en réseau obtiennent toujours des flux d'octets et ils doivent se mettre d'accord sur des protocoles sur la façon d'interpréter ces octets. Cela n'en fait qu'une partie.

3
PSkocik

L'endianisme n'est pas la seule considération. Il y a la taille des entiers, il y a un paquet de structures que vous voudrez peut-être envoyer ou recevoir, etc.

Vous pouvez ignorer tout cela. Personne ne peut te forcer. D'un autre côté, le moyen sûr et fiable consiste à documenter un format externe, puis à écrire du code qui lira ou écrit correctement le format externe, quels que soient votre processeur, votre langage de programmation et l'implémentation de votre langage de programmation.

Ce n'est généralement pas beaucoup de code. Mais cela a un énorme avantage: les personnes qui lisent votre code ne soupçonneront pas que vous êtes ignorant, ne savent rien sur l'échange de données externes et écrivent du code qui ne peut généralement pas faire confiance.

3
gnasher729

Divers protocoles utilisés pour transmettre des données entre serveurs utilisent de petits nombres endiens:

  1. BSON
  2. Tampons de protocole
  3. Capn Proto

Voir https://en.wikipedia.org/wiki/Comparison_of_data_serialization_formats , pour plus de détails sur les différents formats dont certains ont des nombres en petit bout et d'autres ont des nombres en gros bout.

Il n'y a absolument rien de mal à utiliser un protocole basé sur de petits nombres endiens. Une grande machine endienne est tout aussi capable de lire de petits nombres endiens qu'une petite machine endienne peut lire de grands nombres endiens. Beaucoup de gens l'ont fait spécifiquement pour éviter le coût de calcul supplémentaire du décodage des nombres big-endian sur les petites machines endian.

Si vous construisez votre protocole sur l'un de ces protocoles existants, vous n'avez même pas à vous soucier du problème vous-même, il est déjà pris en charge. Lorsque vous décidez d'exécuter votre code sur une plate-forme big-endian, les bibliothèques qui implémentent ces protocoles veilleront automatiquement à ce que vous décodiez les valeurs correctement.

3
Winston Ewert

Un exemple d'un grand système endian est le MIPS utilisé dans les routeurs. Les deux ARM et MIPS sont commutables par endian, mais souvent MIPS est un gros endian car il facilite le matériel réseau (la partie la plus importante d'un Word est la partie que vous recevez en premier et peut faire un routage décision avant d'avoir reçu le reste de la Parole, plutôt que d'avoir à mettre en mémoire tampon la Parole entière).

Cela dépend donc de ce que vous entendez par "Linux", mais si jamais vous souhaitez exécuter votre application serveur sur un système plus petit comme un routeur exécutant OpenWRT, vous devrez peut-être envisager un support endian important.

Comme d'habitude, faire des hypothèses simplificatrices est une optimisation parfaitement sensée jusqu'à ce que vous frappiez quelque chose qui ne correspond pas aux hypothèses. Vous seul pouvez dire à quel point il serait douloureux de les dérouler si jamais vous rencontriez un tel problème.

2
user1908704

Je ne pense pas que les réponses soient assez précises. Selon Wikipedia l'endianité est l'ordre des octets comprenant un mot.

Permet de prendre 4 octets et de les interpréter comme un entier. Dans un petit système endian, les octets seront interprétés de droite à gauche et vice-versa sur un grand système endian. De toute évidence, il est important de s'entendre sur la fin de l'interprétation d'un int.

Permet de faire un zoom arrière un peu sur les protocoles réseau modernes qui pourraient utiliser json ou xml. Aucun de ces formats ne transférera un entier sous forme de 4 octets. Ils transfèrent les données sous forme de texte qui sera analysé en tant qu'intérieur sur le côté récepteur.

Donc, à la fin, l'endianité n'a pas d'importance lors de l'utilisation de json ou xml. Nous devons encore utiliser big endian pour les en-têtes tcp, c'est pourquoi on l'appelle l'ordre des octets du réseau, mais la plupart des programmeurs n'ont pas besoin de jouer avec ceux-ci quotidiennement.

L'encodage le plus largement utilisé aujourd'hui est utf-8 qui peut également être à l'abri des problèmes d'endianité .

Je dirais donc oui. Il est sûr d'ignorer l'endianité lors de l'utilisation de formats basés sur du texte transférés à l'aide d'utf-8.

0

Les grands systèmes endiens semblent en voie de disparition. Beaucoup des unix traditionnels utilisaient du big endian mais ils sont en déclin depuis des années en faveur de linux sur x86.

le bras est bi-endien mais la variante big endian semble être rarement vue.

mips existe dans les deux variantes. Afaict la variante big endian est principalement observée sur les applications de mise en réseau (pour des raisons historiques, les protocoles Internet utilisent généralement le big endian).

ppc était traditionnellement un gros endian avec certaines parties prenant en charge les deux endians mais IBM semble maintenant pousser le petit mode endian pour le ppc 64 bits (ils ont récemment poussé les ports ppc64el dans Debian et Ubuntu).

sparc est normalement gros endian mais semble encore être en déclin.

Si vous implémentez un protocole existant, vous devez évidemment suivre ses spécifications. Si vous voulez que l'IETF bénisse votre nouveau protocole, le big endian sera probablement plus facile, car c'est ce qu'ils utilisent déjà dans leurs protocoles existants, mais IMO pour une nouvelle conception de protocole vert "little endian" est la voie à suivre.

Vous pouvez soit mettre des macros depuis le début qui seront sans opération sur les petits systèmes endiens, soit vous ne pouvez pas déranger jusqu'à/à moins que vous ayez besoin de porter sur un grand système endien.

0
Peter Green