Posso tranquillamente ignorare l'ordine dei byte in rete?


24

Sto sviluppando un'applicazione server-client in cui il client verrà eseguito su Windows e il server probabilmente su Linux. Forse in seguito trasferirò il client su Mac e Linux, ma non ancora.

Tutti i computer di casa in questi giorni funzionano su little-endian. Ho cercato su Google per un po ', ma non sono riuscito a trovare un elenco di dispositivi che girano su big-endian. Per quanto ne so, alcuni chip Motorola usano ancora big-endian e forse alcuni telefoni (non ho intenzione di trasferire l'app su smartphone, quindi non importa per me). Quindi, perché dovrei riorganizzare i byte di ogni intero, ogni breve, ogni float, double, e così via, per la lettura e la scrittura , quando io già so che sia, server e client run on little-endian?

È solo un lavoro inutile da fare. Quindi, la mia domanda è: posso tranquillamente ignorare l'endianness e inviare semplicemente dati little-endian? Quali sono gli svantaggi?


4
Come faranno le macchine a sapere se stanno ricevendo dati little-endian invece dei normali / standard big-endian?
Ixrec,

2
Devi distinguere tra i metadati richiesti dal protocollo di rete e il payload che è solo un mucchio di byte non interpretati per tutti tranne il tuo codice. Spero non stia realizzando il tuo stack di rete. Di conseguenza presumo che la domanda riguardi solo il payload, giusto?

2
@delnan sì, parlando solo del payload. Ovviamente parlerò ancora in ordine di byte di rete con lo stack di rete stesso.
martedì

3
Solo un pensiero a margine: è davvero necessario per te lavorare a un livello di astrazione in cui l'endianità è una preoccupazione? Potrebbe essere utile considerare l'utilizzo di protocolli per i quali esistono librerie appropriate che incapsulano tutto questo "disordine" di basso livello. Quindi, hai anche il bonus aggiuntivo che l'aggiunta di ulteriori clienti può essere fatta molto più facilmente.
godfatherofpolka,

1
@tkausl Solo due ulteriori considerazioni sul lato: come regola generale, l'IO è estremamente lenta rispetto ai calcoli, quindi qualsiasi sovraccarico introdotto lavorando a un livello di astrazione più elevato è molto probabilmente trascurabile. Potrebbe anche accadere che alcune biblioteche superino le implementazioni gestite a mano grazie al pooling intelligente delle risorse e alla gestione asincrona, ecc. Quindi, per prima cosa valuterei attentamente le soluzioni esistenti. Inoltre, data la tua descrizione, spenderei anche alcuni pensieri sulla scalabilità piuttosto che sulle prestazioni, qui potresti nuovamente beneficiare dell'utilizzo di protocolli di livello superiore.
godfatherofpolka,

Risposte:


29

... perché dovrei riordinare i byte ... quando so già che sia server che client funzionano su little endian? Questo è solo un lavoro inutile da fare.

Non è necessario solo se puoi garantire che il tuo codice verrà sempre eseguito su architetture little-endian. Se intendi che abbia una lunga vita, vale la pena lo sforzo extra per evitare di disturbare un codice ben collaudato tra un decennio da quando un'architettura big-endian è diventata la cosa "in" e trovi che sia un buon mercato per la tua applicazione.

Esiste un ordinamento di byte standard di rete. È big-endian, ma nulla dice che devi rispettarlo quando progetti il ​​tuo protocollo. Se sai in anticipo che la maggior parte dei sistemi che eseguono il tuo codice sarà little-endian e le prestazioni sono fondamentali, dichiarare che il "tkausl standard byte order" e procedere con esso. Dove normalmente chiamereste htons()per mettere le cose nell'ordine che vi serve, scrivete una macro chiamata htots()che non si compila condizionalmente su architetture little-endian e fa la riorganizzazione su big-endian.

Mantenere il codice per eseguire le conversioni in entrata e in uscita non è davvero un grande sforzo. Se hai un numero molto elevato di messaggi, trova un modo per esprimerli e scrivi un programma per generare le conversioni in entrata e in uscita.


10
La formulazione when designing your protocolè importante, perché dice anche implicitamente che questa opzione esiste solo quando si progetta un nuovo protocollo e non quando si implementa un protocollo esistente. E menzionando la necessità di una htots(e in realtà un'intera famiglia di funzioni), si chiarisce anche che la scelta di un diverso ordinamento di byte non è qualcosa che si fa per semplificare il codice, ma potrebbe renderlo leggermente più veloce.
Kasperd,

4
Ci sono (non standard, ma molto comune in questi giorni) funzioni htole32(), htole16(), le16toh(), ecc, funzioni disponibili pure. Il file da includere per ottenere questi dichiarati è purtroppo ancora meno standard: <endian.h>o <sys/types.h>dipende dalla piattaforma.
Torek,

Questa risposta va bene, ma penso che il presupposto che la performance possa essere critica nel caso dato sia molto probabilmente un presupposto sbagliato, basato più sulla superstizione che sui fatti.
Doc Brown,

1
@DocBrown: Mi piace sempre sottolineare che il protocollo X ha supportato la scelta del proprio ordine di byte per 30 anni, e per quanto fossero strette le risorse di allora, nessuno si è mai lamentato del fatto che fosse un problema.
Blrfl,

7

È il tuo protocollo.

Non puoi tranquillamente ignorarlo. Ma puoi tranquillamente etichettarlo. Tu controlli il client e il server. Tu controlli il protocollo. Non ha senso non preoccuparsi se è big-endian o little-endian fintanto che sai se entrambe le parti sono d'accordo?

Questo significa spese generali. Ora devi segnare la tua endianness in qualche modo. Fallo e posso leggerlo su qualsiasi cosa.

Se non vuoi sovraccaricare i dati e la tua CPU è annoiata e cerca qualcosa da fare, allora conformati .


6

Quindi, la mia domanda è: posso tranquillamente ignorare l'endianess e inviare semplicemente dati little-endian?

Ci sono due interpretazioni di ciò:

  • Se si progetta il tuo applicazioni / protocolli per sempre 1 send little-endian, allora siete senza ignorare endianess.

  • Se si progettano applicazioni / protocolli per inviare / ricevere qualunque sia l'endianità nativa, funzioneranno finché si eseguiranno le applicazioni su piattaforme con la stessa endianess nativa.

    È "sicuro" 2 ? Questo è per te giudicare! Ma certamente ci sono piattaforme hardware comuni che usano little-endian, big-endian o ... bi-endian.

    Riferimento:

Quali sono gli svantaggi?

L'ovvio svantaggio di ignorare l'endianess è che se tu / i tuoi utenti dovete eseguire le vostre applicazioni / protocollo tra piattaforme con endianess nativi diversi, allora avete un problema. Le applicazioni verranno interrotte e dovrai modificarle per risolvere il problema. E gestire i problemi di compatibilità delle versioni, eccetera.

Chiaramente, la maggior parte delle piattaforme della generazione attuale sono nativamente little-endian, ma 1) alcune non lo sono, e 2) possiamo solo immaginare cosa accadrà in futuro.


1 - Sempre ... anche su piattaforme nativamente big-endian.

2 - In effetti, cosa significa "sicuro"? Se ci stai chiedendo di prevedere la direzione futura delle piattaforme hardware ... Temo che non sia obiettivamente responsabile.


3

L'endianness non è l'unica considerazione. C'è la dimensione di numeri interi, c'è un pacchetto di strutture che potresti voler inviare o ricevere, e così via.

Puoi ignorare tutto questo. Nessuno può costringerti. D'altra parte, il modo sicuro e affidabile è quello di documentare un formato esterno e quindi scrivere il codice che leggerà o scriverà il formato esterno correttamente, indipendentemente dal processore, dal linguaggio di programmazione e dall'implementazione del linguaggio di programmazione.

Di solito non è molto codice. Ma ha un enorme vantaggio: le persone che leggono il tuo codice non sospetteranno di essere all'oscuro, non sanno nulla sull'interscambio di dati esterni e scrivono codice di cui generalmente non ci si può fidare.


3

Lo stack di rete BSD standard in C ha la funzionalità hton/ ntoh( network-to-host/ host-to-network) che si espande fino a non operare su macchine native di rete (big endian). Avresti bisogno delle tue controparti per questi per lo scenario in cui l'ordine di byte nativo della rete è poco endian.

Questo è il modo robusto per farlo.

Non sarebbe convenzionale, ma non vedo nulla di sbagliato in questo. I computer in rete ottengono sempre bytestream e devono concordare protocolli su come interpretare tali byte. Questo è solo una parte.


3

Vari protocolli usati per trasmettere dati tra server usano piccoli numeri endian:

  1. BSON
  2. Buffer di protocollo
  3. Capn Proto

Vedi https://en.wikipedia.org/wiki/Comparison_of_data_serialization_formats , per dettagli su vari formati alcuni dei quali hanno numeri little-endian, e alcuni hanno numeri big-endian.

Non c'è assolutamente nulla di sbagliato nell'usare un protocollo basato su piccoli numeri endian. Una macchina big endian è altrettanto in grado di leggere piccoli numeri endian come una piccola macchina endian può leggere grandi numeri endian. Molte persone lo hanno fatto specificamente per evitare il costo di calcolo extra della decodifica dei numeri big-endian su macchine little endian.

Se costruisci il tuo protocollo sopra uno di questi protocolli esistenti, non devi nemmeno preoccuparti del problema da solo, è già curato. Quando decidi di eseguire il tuo codice su una piattaforma big-endian, le librerie che implementano questi protocolli si prenderanno automaticamente cura di decodificare correttamente i valori.


2

Un esempio di un sistema big endian è il MIPS utilizzato nei router. Sia ARM che MIPS sono commutabili da endian, ma spesso MIPS è big endian perché rende più semplice l'hardware di rete (la parte più significativa di una parola è la parte che ricevi per prima e può prendere una decisione di routing prima di aver ricevuto il resto di la parola, piuttosto che dover bufferizzare l'intera parola).

Quindi dipende da cosa intendi per "Linux", ma se mai vuoi eseguire la tua app server su un sistema più piccolo come un router che esegue OpenWRT, potresti dover considerare il supporto big endian.

Come al solito, fare ipotesi di semplificazione è un'ottimizzazione perfettamente sensata fino a quando si colpisce qualcosa che non si adatta alle ipotesi. Solo tu puoi dire quanto sarebbe doloroso rilassarli se mai incontrassi un problema del genere.


0

Non credo che nessuna delle risposte sia abbastanza precisa. Secondo Wikipedia l' endianness è l'ordine dei byte che comprende una parola.

Consente di prendere 4 byte e di interpretarli come int. Un sistema un po 'endiano i byte saranno interpretati da destra a sinistra e viceversa su un sistema big endian. Ovviamente è importante concordare su quale fine interpretare un int.

Consente di ridurre leggermente i protocolli di rete moderni che potrebbero utilizzare json o xml. Nessuno di questi formati trasferirà un int come 4 byte. Trasferiranno i dati come testo che verrà analizzato come int sul lato ricevente.

Quindi alla fine l'endianness non ha importanza quando si utilizza json o xml. Dobbiamo ancora usare big endian per le intestazioni di tcp, motivo per cui si chiama ordine dei byte di rete, ma la maggior parte dei programmatori non ha bisogno di pasticciare con quelli su base giornaliera.

La codifica più utilizzata per lo più oggi è utf-8 che sembra essere immune anche ai problemi relativi all'endianità .

Quindi direi di si. È sicuro ignorare l'endianità quando si usano formati basati su testo trasferiti usando utf-8.


due voti negativi e nessun commento. Grande.
Esben Skov Pedersen,

1
Non ero il downvoter ma questa risposta sembra ignorare / respingere una domanda perfettamente valida. Solo perché alcuni protocolli sono basati su testo non significa che tutti i protocolli dovrebbero esserlo.
Peter Green,

2
Ho valutato questo perché tocca il fatto che il formato del payload non ha nulla a che fare con i protocolli sottostanti. Alcune persone adorano scavare in problemi inventati.
Zdenek,

0

I sistemi big endian sembrano uscire. Molti degli unix tradizionali hanno usato big endian ma sono in declino da anni a favore di Linux su x86.

arm è bi-endian ma la variante big endian sembra essere vista raramente.

mips esiste in entrambe le varianti. Afaict la variante del big endian è vista principalmente sulle applicazioni di rete (per ragioni storiche i protocolli di Internet usano generalmente il big endian).

ppc era tradizionalmente big endian con alcune parti che supportano entrambi gli endian ma IBM sembra ora spingere la modalità little endian per ppc a 64 bit (recentemente hanno spinto le porte ppc64el in Debian e Ubuntu).

sparc è normalmente big endian ma sembra di nuovo essere in declino.

Se stai implementando un protocollo esistente, ovviamente devi seguire le sue specifiche. Se vuoi che l'IETF benedica il tuo nuovo protocollo, è probabile che il big endian sia più facile perché è quello che usano già nei loro protocolli esistenti, ma IMO per un nuovo design del protocollo "greenfield" little endian è la strada da percorrere.

Puoi inserire macro dall'inizio che non saranno operative su sistemi little endian o non puoi disturbare fino a quando non hai bisogno di port su un sistema big endian.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.