Tworzę aplikację serwer-klient, w której klient będzie działał w systemie Windows, a serwer prawdopodobnie w systemie Linux. Może później przeniosę klienta na komputery Mac i Linux, ale jeszcze nie teraz.
Wszystkie komputery domowe działają obecnie na little-endian. Przez pewien czas korzystałem z Google, ale tak naprawdę nie mogłem znaleźć listy urządzeń, które działają na big-endian. O ile mi wiadomo, niektóre układy Motorola nadal używają big-endian i może niektórych telefonów (nie planuję przenosić aplikacji na smartfony, więc nie ma to dla mnie znaczenia). Dlaczego więc miałbym zmieniać kolejność bajtów każdej liczby całkowitej, każdej krótkiej, każdej liczby zmiennoprzecinkowej, podwójnej itd. Do czytania i pisania , skoro już wiem, że zarówno serwer, jak i klient działają na little-endian?
To po prostu niepotrzebna praca. Więc moje pytanie brzmi: czy mogę bezpiecznie zignorować endianness i po prostu wysłać dane little-endian? Jakie są wady?
źródło
Odpowiedzi:
Nie jest to konieczne, jeśli możesz zagwarantować, że Twój kod będzie zawsze działał na architekturze little-endian. Jeśli zamierzasz mieć długą żywotność, warto podjąć dodatkowy wysiłek, aby uniknąć zakłócania sprawdzonego kodu za dekadę, gdy jakaś architektura big-endian stała się „wcielona” i okazuje się, że jest to dobry rynek dla Twoje zgłoszenie.
Istnieje standardowe bajtowe porządkowanie sieci. Jest to big-endian, ale nic nie mówi, że musisz go przestrzegać przy projektowaniu protokołu. Jeśli wiesz z wyprzedzeniem, że większość systemów, w których działa Twój kod, będzie mało wydajna, a wydajność ma krytyczne znaczenie, zadeklaruj, że „standardowe porządkowanie bajtów tkausl” i idź z nim. Tam, gdzie normalnie dzwonisz,
htons()
aby uporządkować potrzebne rzeczy, napisz makro o nazwiehtots()
warunkowo, które kompiluje się do niczego na architekturach little-endian i dokonuje ponownej aranżacji na big-endian.Utrzymanie kodu do konwersji przychodzących i wychodzących nie jest tak naprawdę dużym wysiłkiem. Jeśli masz bardzo dużą liczbę wiadomości, znajdź sposób na ich wyrażenie i napisanie programu do generowania konwersji przychodzących i wychodzących.
źródło
when designing your protocol
jest ważne, ponieważ domyślnie mówi również, że ta opcja istnieje tylko przy projektowaniu nowego protokołu, a nie przy implementacji niektórych istniejących protokołów. A wzmianka o potrzebiehtots
(a właściwie całej rodziny funkcji) również wyjaśnia, że wybranie innej kolejności bajtów nie jest rzeczą, którą należy uprościć, ale może to nieco przyspieszyć.htole32()
,htole16()
,le16toh()
, itd., A także funkcje dostępne. Plik, który należy dołączyć, aby je zadeklarować, jest niestety jeszcze mniej standardowy:<endian.h>
lub<sys/types.h>
zależy od platformy.To twój protokół.
Nie możesz tego bezpiecznie zignorować. Ale możesz to bezpiecznie oznaczyć. Kontrolujesz klienta i serwer. Kontrolujesz protokół. Czy nie ma sensu nie przejmować się, czy jest to big-endian czy little-endian, o ile wiesz, czy obie strony się zgadzają?
To oznacza narzut. Teraz musisz jakoś zaznaczyć swoją endianizm. Zrób to, a mogę to przeczytać na wszystkim.
Jeśli nie chcesz narzutu danych, a Twój procesor jest znudzony i szuka czegoś do zrobienia, dostosuj się .
źródło
Istnieją dwie interpretacje tego:
Jeśli projektujesz swoje aplikacje / protokoły tak, aby zawsze 1 wysyłały little-endian, NIE ignorujesz endianess.
Jeśli projektujesz swoje aplikacje / protokoły tak, aby wysyłały / odbierały, czymkolwiek jest natywna endianess, będą one działać tak długo, jak długo będziesz uruchamiać aplikacje na platformach z tą samą natywną endianessą.
Czy to „bezpieczne” 2 ? To ty musisz osądzić! Ale z pewnością istnieją popularne platformy sprzętowe, które używają little-endian, big-endian lub ... bi-endian.
Odniesienie:
Oczywistą wadą ignorowania endianess jest to, że jeśli Ty / Twoi użytkownicy musicie uruchamiać swoje aplikacje / protokół między platformami o różnych natywnych endianessach, to masz problem. Aplikacje się zepsują i będziesz musiał je zmienić, aby rozwiązać problem. I radzić sobie z problemami ze zgodnością wersji itp.
Najwyraźniej większość platform obecnej generacji jest natywnie endian, ale 1) niektóre nie są, i 2) możemy tylko zgadywać, co się stanie w przyszłości.
1 - Zawsze ... w tym na platformach, które są natywnie big-endianami.
2 - Rzeczywiście, co oznacza „bezpieczny”? Jeśli pytasz nas o przewidywanie przyszłego kierunku platform sprzętowych ... Obawiam się, że nie jest to obiektywnie możliwe.
źródło
Endianizm nie jest jedynym czynnikiem. Istnieje wielkość liczb całkowitych, istnieje pakiet struktur, które możesz chcieć wysłać lub odebrać, i tak dalej.
Możesz to wszystko zignorować. Nikt cię nie zmusi. Z drugiej strony, bezpiecznym i niezawodnym sposobem jest udokumentowanie formatu zewnętrznego, a następnie napisanie kodu, który poprawnie odczytuje lub zapisuje format zewnętrzny, bez względu na procesor, język programowania i implementację języka programowania.
Zwykle nie jest to dużo kodu. Ma to jednak ogromną zaletę: osoby czytające Twój kod nie będą podejrzewać, że nie masz pojęcia, nie wiedzą nic o zamianie danych zewnętrznych i piszą kody, którym generalnie nie można ufać.
źródło
Standardowy stos sieciowy BSD w C ma
hton
/ntoh
funkcjonalność (network-to-host
/host-to-network
), która rozszerza się na brak operacji na natywnych komputerach sieciowych (big endian). Będziesz potrzebował własnych odpowiedników do tego scenariusza, w którym natywna kolejność bajtów w sieci jest niewielka.To niezawodny sposób na zrobienie tego.
Byłoby to niekonwencjonalne, ale nie widzę w tym nic złego. Komputery w sieci zawsze otrzymują strumienie bajtów i muszą uzgodnić protokoły interpretacji tych bajtów. To tylko część tego.
źródło
Różne protokoły używane do przesyłania danych między serwerami używają niewielkich liczb endianowych:
Zobacz https://en.wikipedia.org/wiki/Comparison_of_data_serialization_formats , aby uzyskać szczegółowe informacje na temat różnych formatów, z których niektóre mają liczby little-endian, a niektóre mają liczby big-endian.
Nie ma absolutnie nic złego w stosowaniu protokołu opartego na małych liczbach endianowych. Duża maszyna endian jest w stanie równie dobrze odczytywać małe liczby endian, jak mała maszyna endian może czytać duże liczby endian. Wiele osób zrobiło to specjalnie, aby uniknąć dodatkowych kosztów obliczeniowych związanych z dekodowaniem liczb big-endian na małych komputerach endian.
Jeśli zbudujesz swój protokół na jednym z tych istniejących protokołów, nie musisz nawet sam martwić się o problem, który już został rozwiązany. Jeśli zdecydujesz się uruchomić swój kod na platformie big-endian, biblioteki, które implementują te protokoły, automatycznie zadbają o to, aby poprawnie zdekodować wartości.
źródło
Jednym z przykładów dużego systemu endian jest MIPS stosowany w routerach. Zarówno ARM, jak i MIPS są przełączane przez endian, ale często MIPS jest dużym endianem, ponieważ sprawia, że sprzęt sieciowy jest łatwiejszy (najważniejsza część słowa to część, którą otrzymujesz jako pierwsza i może podjąć decyzję o routingu, zanim otrzymasz resztę słowo zamiast buforować całe słowo).
To zależy od tego, co rozumiesz przez „Linux”, ale jeśli kiedykolwiek będziesz chciał uruchomić aplikację serwera na mniejszym systemie, takim jak router z OpenWRT, być może będziesz musiał rozważyć wsparcie dla dużego endianu.
Jak zwykle, upraszczanie założeń jest optymalną rozsądną optymalizacją, dopóki nie trafisz na coś, co nie pasuje do założeń. Tylko Ty możesz powiedzieć, jak bolesne byłoby ich odprężyć, jeśli kiedykolwiek spotkasz się z takim problemem.
źródło
Nie sądzę, aby którakolwiek z odpowiedzi była dość precyzyjna. Według Wikipedii endianness to kolejność bajtów zawierających słowo.
Weźmy 4 bajty i zinterpretujmy je jako liczbę całkowitą. Jeden mały system endianowy, bajty będą interpretowane od prawej do lewej i vice-verca w dużym systemie endianowym. Oczywiście ważne jest, aby ustalić, który koniec interpretować int.
Pozwala trochę pomniejszyć współczesne protokoły sieciowe, które mogą używać json lub xml. Żaden z tych formatów nie przeniesie int jako 4 bajty. Przekażą dane jako tekst, który zostanie przeanalizowany jako int po stronie odbierającej.
Więc w końcu endianness nie ma znaczenia, gdy używasz json lub xml. Nadal musimy używać big endian dla nagłówków tcp, dlatego nazywa się to porządkiem bajtów sieciowych, ale większość programistów nie musi codziennie z nimi zadzierać.
Najczęściej stosowanym obecnie kodowaniem jest utf-8, który bywa odporny na problemy związane z endianizmem .
Więc powiedziałbym tak. Bezpieczne jest ignorowanie endianizmu podczas korzystania z formatów tekstowych przesyłanych za pomocą utf-8.
źródło
Wydaje się, że duże systemy endianów wychodzą. Wiele tradycyjnych uniksów używało Big Endian, ale od lat spada na korzyść Linuksa na x86.
ramię jest bi-endian, ale duży wariant endianu wydaje się być rzadko spotykany.
mips istnieje w obu wariantach. Podobno wariant Big Endian jest najczęściej spotykany w aplikacjach sieciowych (z powodów historycznych protokoły internetowe zazwyczaj używają Big Endian).
ppc był tradycyjnie dużym endianem, z niektórymi częściami obsługującymi oba endiany, ale IBM wydaje się teraz pchać mały tryb endian dla 64-bitowego ppc (ostatnio wypchnął porty ppc64el do Debiana i Ubuntu).
sparc jest zwykle dużym endianem, ale znów wydaje się podupadać.
Jeśli wdrażasz istniejący protokół, oczywiście musisz przestrzegać jego specyfikacji. Jeśli chcesz, aby IETF pobłogosławił twój nowy protokół, prawdopodobnie duży endian będzie łatwiejszy, ponieważ już tego używają w swoich istniejących protokołach, ale IMO dla nowego projektu protokołu „greenfield”, mały endian, jest dobrym rozwiązaniem.
Możesz albo wstawiać makra od samego początku, które nie będą działać na małych systemach endianowych, albo nie możesz zawracać sobie głowy dopóki / chyba, że będziesz musiał przenieść się do dużego systemu endianowego.
źródło