Ich entwickle eine Server-Client-Anwendung, bei der der Client unter Windows und der Server wahrscheinlich unter Linux ausgeführt wird. Vielleicht portiere ich den Client später auf Mac und Linux, aber noch nicht.
Alle Heimcomputer laufen heutzutage auf Little-Endian. Ich habe eine Weile gegoogelt, aber ich konnte nicht wirklich eine Liste von Geräten finden, die auf Big-Endian laufen. Soweit ich weiß, verwenden einige Motorola-Chips immer noch Big-Endian und möglicherweise einige Telefone (ich habe nicht vor, die App auf Smartphones zu portieren, das ist mir also egal). Warum sollte ich die Bytes jeder ganzen Zahl, jeder kurzen Zahl, jeder Gleitkommazahl, jeder doppelten Zahl usw. zum Lesen und Schreiben neu anordnen , wenn ich bereits weiß, dass sowohl Server als auch Client auf Little-Endian ausgeführt werden?
Das ist nur unnötige Arbeit. Meine Frage lautet also: Kann ich die Endianität ignorieren und nur Little-Endian-Daten senden? Was sind die Nachteile?
quelle
Antworten:
Es ist nur unnötig, wenn Sie garantieren können, dass Ihr Code immer auf Little-Endian-Architekturen ausgeführt wird. Wenn Sie sich eine lange Lebensdauer wünschen, lohnt es sich, in einem Jahrzehnt, in dem einige Big-Endian-Architekturen zum "In" -Ding geworden sind und Sie der Meinung sind, dass dies ein guter Markt für Code ist, nicht mehr zu stören Ihre Bewerbung.
Es gibt eine Netzwerkstandard-Bytereihenfolge. Es ist Big-Endian, aber nichts sagt, dass Sie sich bei der Gestaltung Ihres Protokolls daran halten müssen. Wenn Sie im Voraus wissen, dass die Mehrheit der Systeme, auf denen Ihr Code ausgeführt wird, Little-Endian-Systeme sind und die Leistung kritisch ist, deklarieren Sie die "tkausl standard byte ordering" und folgen Sie ihr. Wo Sie normalerweise anrufen
htons()
, um die Dinge in die von Ihnen benötigte Reihenfolge zu bringen, schreiben Sie ein Makro mit dem Namenhtots()
, das auf Little-Endian-Architekturen unter bestimmten Bedingungen zu nichts kompiliert und auf Big-Endian neu arrangiert wird.Es ist nicht wirklich ein großer Aufwand, den Code für die eingehenden und ausgehenden Konvertierungen beizubehalten. Wenn Sie eine sehr große Anzahl von Nachrichten haben, suchen Sie nach einer Möglichkeit, diese auszudrücken, und schreiben Sie ein Programm, um die eingehenden und ausgehenden Konvertierungen zu generieren.
quelle
when designing your protocol
ist wichtig, da implizit festgelegt ist, dass diese Option nur beim Entwerfen eines neuen Protokolls und nicht beim Implementieren eines vorhandenen Protokolls vorhanden ist. Wenn man die Notwendigkeit einerhtots
(und wirklich einer ganzen Familie von Funktionen) erwähnt, wird auch klar, dass die Auswahl einer anderen Byte-Reihenfolge nicht dazu dient, den Code zu vereinfachen, sondern ihn möglicherweise etwas schneller zu machen.htole32()
,htole16()
,le16toh()
etc. Funktionen zur Verfügung. Die Datei, die eingeschlossen werden muss, um diese deklariert zu bekommen, ist leider noch weniger standardisiert:<endian.h>
oder<sys/types.h>
abhängig von der Plattform.Es ist dein Protokoll.
Sie können es nicht sicher ignorieren. Aber Sie können es sicher beschriften. Sie steuern den Client und den Server. Sie steuern das Protokoll. Ist es nicht sinnvoll, sich nicht darum zu kümmern, ob es sich um Big-Endian oder Little-Endian handelt, solange Sie wissen, ob beide Seiten einverstanden sind?
Das bedeutet Overhead. Jetzt musst du deine Endianness irgendwie markieren. Tun Sie das, und ich kann es auf alles lesen.
Wenn Sie keinen Daten-Overhead wünschen und Ihre CPU gelangweilt ist und etwas zu tun sucht, passen Sie sich an .
quelle
Dafür gibt es zwei Interpretationen:
Wenn Sie Ihre Anwendungen / Protokolle so gestalten, dass immer 1 Little-Endian gesendet wird, ignorieren Sie Endianess NICHT.
Wenn Sie Ihre Anwendungen / Protokolle so entwerfen, dass sie unabhängig von der nativen Endianess gesendet / empfangen werden, funktionieren sie, solange Sie Ihre Anwendungen auf Plattformen mit derselben nativen Endianess ausführen.
Ist das "sicher" 2 ? Das müssen Sie beurteilen! Aber sicherlich gibt es gängige Hardware-Plattformen, die Little-Endian, Big-Endian oder ... Bi-Endian verwenden.
Referenz:
Der offensichtliche Nachteil des Ignorierens von Endianess besteht darin, dass Sie ein Problem haben, wenn Sie / Ihre Benutzer Ihre Anwendungen / Protokolle zwischen Plattformen mit unterschiedlichen nativen Endianess ausführen müssen. Die Anwendungen brechen ab, und Sie müssen sie ändern, um das Problem zu beheben. Und mit Versionskompatibilitätsproblemen usw. umgehen.
Natürlich sind die meisten Plattformen der aktuellen Generation von Haus aus Little-Endian-Plattformen, aber 1) einige sind es nicht, und 2) wir können nur raten, was in Zukunft passieren wird.
1 - Immer ... auch auf Plattformen, die von Haus aus Big-Endian sind.
2 - Was bedeutet eigentlich "sicher"? Wenn Sie uns bitten, die zukünftige Richtung von Hardwareplattformen vorherzusagen ... Ich fürchte, das ist objektiv nicht zu beantworten.
quelle
Endianness ist nicht die einzige Überlegung. Es gibt die Größe von Ganzzahlen, das Packen von Strukturen, die Sie senden oder empfangen möchten, und so weiter.
Sie können das alles ignorieren. Niemand kann dich zwingen. Auf der anderen Seite besteht die sichere und zuverlässige Möglichkeit darin, ein externes Format zu dokumentieren und dann Code zu schreiben, der das externe Format korrekt liest oder schreibt, unabhängig von Ihrem Prozessor, Ihrer Programmiersprache und der Implementierung Ihrer Programmiersprache.
Normalerweise ist es nicht viel Code. Aber es hat einen enormen Vorteil: Leute, die Ihren Code lesen, ahnen nicht, dass Sie ahnungslos sind, wissen nichts über den Austausch externer Daten und schreiben Code, dem im Allgemeinen nicht vertraut werden kann.
quelle
Der Standard-BSD-Networking-Stack in C verfügt über die Funktion
hton
/ntoh
(network-to-host
/host-to-network
), die auf netzwerkgebundenen Rechnern (Big Endian) zu No-Ops erweitert wird. Für das Szenario, in dem die netzwerkspezifische Bytereihenfolge Little Endian ist, benötigen Sie Ihre eigenen Gegenstücke.Das ist der robuste Weg.
Es wäre unkonventionell, aber ich sehe nichts falsch daran. Netzwerkcomputer erhalten immer Byteströme und müssen sich auf Protokolle einigen, wie diese Bytes interpretiert werden sollen. Dies ist nur ein Teil davon.
quelle
Verschiedene Protokolle zur Datenübertragung zwischen Servern verwenden Little-Endian-Nummern:
Unter https://en.wikipedia.org/wiki/Comparison_of_data_serialization_formats finden Sie Details zu verschiedenen Formaten, von denen einige Little-Endian-Zahlen und einige Big-Endian-Zahlen aufweisen.
Es ist absolut nichts Falsches daran, ein Protokoll zu verwenden, das auf Little-Endian-Zahlen basiert. Ein Big-Endian-Rechner kann kleine Endian-Zahlen genauso lesen wie ein Little-Endian-Rechner große Endian-Zahlen. Viele Leute haben es speziell getan, um die zusätzlichen Berechnungskosten für das Decodieren von Big-Endian-Zahlen auf Little-Endian-Maschinen zu vermeiden.
Wenn Sie Ihr Protokoll auf einem dieser vorhandenen Protokolle aufbauen, müssen Sie sich nicht einmal um das Problem selbst kümmern, es ist bereits erledigt. Wenn Sie sich entscheiden, Ihren Code auf einer Big-Endian-Plattform auszuführen, sorgen die Bibliotheken, die diese Protokolle implementieren, automatisch dafür, dass Sie die Werte korrekt dekodieren.
quelle
Ein Beispiel für ein Big-Endian-System ist das in Routern verwendete MIPS. Sowohl ARM als auch MIPS können auf Endian umgeschaltet werden. Häufig handelt es sich bei MIPS jedoch um Big Endian, da dies die Netzwerkhardware vereinfacht (der wichtigste Teil eines Wortes ist der Teil, den Sie zuerst erhalten und der eine Routing-Entscheidung treffen kann, bevor Sie den Rest erhalten haben) das Wort, anstatt das ganze Wort puffern zu müssen).
Es hängt also davon ab, was Sie unter "Linux" verstehen. Wenn Sie Ihre Server-App jedoch jemals auf einem kleineren System wie einem Router mit OpenWRT ausführen möchten, müssen Sie möglicherweise die Big-Endian-Unterstützung in Betracht ziehen.
Wie üblich ist die Vereinfachung von Annahmen eine absolut sinnvolle Optimierung, bis Sie auf etwas stoßen, das nicht zu den Annahmen passt. Nur Sie können sagen, wie schmerzhaft es wäre, sie abzuwickeln, wenn Sie jemals auf ein solches Problem stoßen.
quelle
Ich glaube nicht, dass eine der Antworten genau genug ist. Endianness ist laut Wikipedia die Reihenfolge der Bytes, aus denen ein Wort besteht.
Nehmen wir 4 Bytes und interpretieren sie als int. Bei einem Little-Endian-System werden die Bytes von rechts nach links und bei einem Big-Endian-System umgekehrt interpretiert. Offensichtlich ist es wichtig zu vereinbaren, welches Ende ein Int. Interpretieren soll.
Lassen Sie uns ein bisschen auf moderne Netzwerkprotokolle eingehen, die json oder xml verwenden könnten. Keines dieser Formate überträgt ein Int mit 4 Bytes. Sie übertragen die Daten als Text, der auf der Empfängerseite als int analysiert wird.
Am Ende spielt Endianness also keine Rolle, wenn Sie json oder xml verwenden. Wir müssen immer noch Big Endian für TCP-Header verwenden, weshalb es als Netzwerk-Bytereihenfolge bezeichnet wird, aber die meisten Programmierer müssen sich nicht täglich damit herumschlagen.
Die am weitesten verbreitete Codierung ist heute meistens utf-8, die auch vor Problemen in Bezug auf Endianität gefeit sein kann .
Also würde ich ja sagen. Es ist sicher, Endianness zu ignorieren, wenn textbasierte Formate verwendet werden, die mit utf-8 übertragen wurden.
quelle
Big-Endian-Systeme scheinen auf dem Weg nach draußen zu sein. Viele der traditionellen Unixe verwendeten Big Endian, aber sie sind seit Jahren zugunsten von Linux auf x86 rückläufig.
Arm ist Bi-Endian, aber die Big-Endian-Variante scheint selten zu sehen zu sein.
Mips gibt es in beiden Varianten. Die Big-Endian-Variante wird hauptsächlich bei Netzwerkanwendungen verwendet (aus historischen Gründen verwenden Internetprotokolle im Allgemeinen Big-Endian).
ppc war traditionell Big-Endian mit einigen Teilen, die beide Endian unterstützen, aber IBM scheint nun den Little-Endian-Modus für 64-Bit-ppc voranzutreiben (sie haben kürzlich ppc64el-Ports in Debian und Ubuntu verschoben).
sparc ist normalerweise big endian, scheint aber wieder rückläufig zu sein.
Wenn Sie ein vorhandenes Protokoll implementieren, müssen Sie dessen Spezifikationen natürlich befolgen. Wenn Sie möchten, dass die IETF Ihr neues Protokoll segnet, ist Big Endian wahrscheinlich einfacher, da dies bereits in den vorhandenen Protokollen verwendet wird. IMO für ein neues "Greenfield" -Protokoll ist Little Endian jedoch der richtige Weg.
Sie können entweder von Anfang an Makros einfügen, die auf Little-Endian-Systemen nicht ausgeführt werden, oder Sie können sich erst darum kümmern, wenn Sie auf ein Big-Endian-System portieren müssen.
quelle