Чи можу я сміливо ігнорувати порядок байтів у мережі?


24

Я розробляю серверно-клієнтську програму, де клієнт буде працювати в Windows, а сервер, ймовірно, на Linux. Можливо, я згодом переведу клієнта на Mac та Linux, але поки що.

Усі домашні комп’ютери в ці дні працюють на малопомітних. Я деякий час гугла, але мені не вдалося знайти список пристроїв, які працюють на big-endian. Наскільки я знаю, деякі мікросхеми Motorola все ще використовують біг-ендіан і, можливо, деякі телефони (я не планую переносити додаток на смартфони, тому для мене це не має значення). Отже, навіщо я переставляти байти кожного цілого числа, кожного короткого, кожного плаваючого, подвійного і т. Д. Для читання і запису , коли я вже знаю, що і сервер, і клієнт працюють на малопомітному?

Це просто зайва робота. Отже, моє запитання таке: чи можу я сміливо ігнорувати цілеспрямованість і просто надсилати дані мало-ендіанських? Які недоліки?


4
Як машини дізнаються, чи отримують вони дані мало-ендіанських замість звичайних / стандартних даних великих ендіанів?
Іксрек

2
Вам потрібно розрізнити метадані, необхідні мережевим протоколом, і корисним навантаженням, що становить лише купу неінтерпретованих байтів для всіх, крім вашого коду. Я сподіваюся, що ви не прокатуєте власну мережу. Отже, я припускаю, що питання стосується лише корисного навантаження, правда?

2
@delnan так, говорити лише про корисне навантаження. Я, звичайно, все ще поговорю в мережевому байті до самого мережевого стека.
tkausl

3
Лише думка на стороні: чи справді вам потрібно працювати на рівні абстракції, де турбота викликає загрозу? Можливо, варто подумати про використання протоколів, для яких існують відповідні бібліотеки, які інкапсулюють всю цю "безладу" низького рівня. Тоді ви також маєте додатковий бонус, що додавати подальших клієнтів можна набагато простіше.
godfatherofpolka

1
@tkausl Ще дві думки з боку: Як правило, IO надзвичайно повільний у порівнянні з обчисленнями, тому будь-які накладні витрати, введені роботою на більш високому рівні абстракції, швидше за все, незначні. Можливо, навіть трапляється, що деякі бібліотеки перевершують керовані реалізації завдяки розумному об'єднанню ресурсів та асинхронному обробленню тощо. Отже, я б спочатку ретельно оцінив існуючі рішення. Крім того, враховуючи ваше опис, я б також витратив деякі думки на масштабованість, а не на продуктивність, тут ви знову можете отримати користь від використання протоколів вищого рівня.
godfatherofpolka

Відповіді:


29

... навіщо мені переставляти байти ... коли я вже знаю, що і сервер, і клієнт працюють на маленькому ендіані? Це просто непотрібна робота.

Це непотрібно лише в тому випадку, якщо ви можете гарантувати, що ваш код завжди працюватиме в архітектурах малої ендіанської економіки. Якщо ви маєте намір тривалий термін життя, варто докласти додаткових зусиль, щоб не порушувати добре перевірений код через десятиліття, коли якась архітектура великого ендіану стала річчю "в", і ви вважаєте, що це хороший ринок для ваша заявка.

Існує стандартне мережеве впорядкування байтів. Це великий ендіаніст, але нічого не говорить про те, що ви повинні дотримуватися цього при розробці свого протоколу. Якщо ви заздалегідь знаєте, що більшість систем, що працюють з вашим кодом, будуть малоефективними, а продуктивність є критичною, заявіть, що "стандартне замовлення байтів tkausl", і перейдіть з ним. Там, де ви зазвичай зателефонуєте, htons()щоб навести речі в потрібному вам порядку, напишіть макрос, який називається, htots()який умовно компілюється ні до чого в архітектурах маленьких ендіан і робить перестановку на big-endian.

Підтримка коду для здійснення вхідної та вихідної конверсій насправді не є великим зусиллям. Якщо у вас дуже велика кількість повідомлень, знайдіть спосіб їх виразити та напишіть програму для генерації вхідних та вихідних перетворень.


10
Формулювання when designing your protocolє важливим, оскільки воно також неявно говорить про те, що цей варіант існує лише при розробці нового протоколу, а не при реалізації деякого існуючого протоколу. І згадуючи про необхідність htots(і справді цілого сімейства функцій), також зрозуміло, що вибір іншого впорядкування байтів - це не те, що потрібно зробити для спрощення коду, але це може зробити його трохи швидшим.
kasperd

4
Є (нестандартні , але дуже часто в ці дні) функції htole32(), htole16(), le16toh()і т.д., доступні функції , а також. На жаль, файл, який потрібно включити для декларування, є ще менш стандартним: <endian.h>або <sys/types.h>залежно від платформи.
Торек

Ця відповідь чудова, але я вважаю, що припущення про те, що виконання може бути критичним, даний випадок, швидше за все, є помилковим припущенням, що базується більше на забобонах, ніж на фактах.
Doc Brown

1
@DocBrown: Я завжди хотів би зазначити, що протокол X підтримує вибір вашого байтового замовлення протягом 30 років, і настільки ж тісно, ​​як тоді були ресурси, ніхто ніколи не скаржився, що це проблема.
Blrfl

7

Це ваш протокол.

Ви не можете сміливо ігнорувати це. Але ви можете сміливо позначити це. Ви керуєте клієнтом і сервером. Ви керуєте протоколом. Чи не має сенсу не байдуже, чи великий ендіанець, чи малий ендіанець, поки ви знаєте, чи згодні обидві сторони?

Це означає накладні витрати. Тепер ви повинні якось позначити свою витривалість. Зробіть це, і я можу прочитати його на будь-що.

Якщо ви не хочете, щоб дані накладні, а ваш процесор нудьгував і шукає, що робити, то відповідайте .


6

Отже, моє запитання таке: чи можу я сміливо ігнорувати ендіатизм і просто надсилати малоекземлянські дані?

Є два тлумачення цього:

  • Якщо ви розробляєте свої додатки / протоколи, щоб завжди надсилати 1 маленький ендіан, то ви НЕ ігноруєте ендіас.

  • Якщо ви розробляєте свої програми / протоколи для надсилання / отримання будь-якої рідної ендіазності, вони працюватимуть до тих пір, поки ви запускаєте ваші програми на платформах з тією ж самою націленістю.

    Це "безпечно" 2 ? Це вам судити! Але, безумовно, існують загальні апаратні платформи, які використовують малоепійські, великі-ендіанські або ... бі-ендіанські.

    Довідка:

Які недоліки?

Очевидним недоліком ігнорування ендіасності є те, що якщо вам / вашим користувачам потрібно запускати ваші програми / протокол між платформами, що мають іншу природну ендіазність, у вас виникає проблема. Програми зламаються, і вам потрібно буде їх змінити, щоб усунути проблему. І вирішуйте проблеми сумісності версій, тощо.

Зрозуміло, що більшість платформ поточного покоління є споконвічно малоінтенсивними, але 1) деякі це не так, і 2) ми можемо лише здогадуватися, що буде в майбутньому.


1 - Завжди ... в тому числі на платформах, які є споконвічно великими ендіанами.

2 - Справді, що означає "безпечний"? Якщо ви просите нас передбачити майбутній напрям апаратних платформ ... Я боюся, що це об'єктивно не відповідає.


3

Ендіанство - це не єдиний розгляд. Існує розмір цілих чисел, є упаковка структур, які ви, можливо, захочете надіслати чи отримати тощо.

Ви можете проігнорувати все це. Ніхто не може вас змусити. З іншого боку, безпечним і надійним способом є документальне оформлення зовнішнього формату, а потім написання коду, який буде правильно читати або записувати зовнішній формат, незалежно від того, яким є ваш процесор, ваша мова програмування та реалізація вашої мови програмування.

Зазвичай це не так багато коду. Але це має величезну користь: люди, які читають ваш код, не підозрюють, що ви неосвічені, нічого не знаєте про обмін зовнішніми даними та пишуть код, якому взагалі не можна довіряти.


3

Стандартний мережевий стек BSD в C має hton/ ntohфункціональність ( network-to-host/ host-to-network), яка розширюється до відсутності операційних можливостей на власних мережевих машинах (big endian) Вам знадобляться власні аналоги до них для сценарію, в якому порядок передачі байтів у мережі є незначним.

Це надійний спосіб зробити це.

Це було б нетрадиційно, але я не бачу в цьому нічого поганого. Мережеві комп'ютери завжди отримують швидкі потоки, і їм потрібно узгодити протоколи про те, як інтерпретувати ці байти. Це лише частина цього.


3

Різні протоколи, що використовуються для передачі даних між серверами, використовують невеликі ендіанські числа:

  1. BSON
  2. Буфери протоколів
  3. Capn Proto

Докладнішу інформацію про різні формати див. На https://en.wikipedia.org/wiki/Comppare_of_data_serialization_formats , деякі з яких мають мало-ендіанські номери, а деякі мають великі-ендіанські номери.

Немає нічого поганого у використанні протоколу, заснованого на маленьких ендіанських номерах. Велика ендіанська машина настільки ж здатна читати маленькі ендіанські числа, як і маленька ендіанська машина може читати великі ендіанські числа. Багато людей зробили це спеціально, щоб уникнути зайвих обчислювальних витрат на розшифровку великих ендіанських чисел на маленьких ендіанських машинах.

Якщо ви будуєте свій протокол на одному з цих існуючих протоколів, вам навіть не доведеться турбуватися про проблему самостійно, про її вже вирішено. Коли ви вирішите запустити свій код на платформі big-endian, то бібліотеки, які реалізують ці протоколи, автоматично подбають про те, щоб правильно розшифрувати значення.


2

Одним із прикладів великої ендіанської системи є MIPS, що використовується в маршрутизаторах. І ARM, і MIPS є перемикачами, але часто MIPS є великим ендіаном, оскільки це спрощує мережеве обладнання (найзначніша частина слова - це частина, яку ви отримаєте першою, і може прийняти рішення про маршрутизацію, перш ніж ви отримаєте решту слово, а не буферизація всього слова).

Отже, це залежить від того, що ви маєте на увазі під "Linux", але якщо ви хочете коли-небудь запустити свою серверну програму на меншій системі, наприклад, на маршрутизаторі, на якому працює OpenWRT, можливо, вам доведеться врахувати велику підтримку endian.

Як завжди, спрощення припущень є цілком розумною оптимізацією до тих пір, поки ви не потрапите на щось, що не відповідає припущенням. Тільки ви можете сказати, як боляче було б розкручувати їх, якщо ви коли-небудь стикаєтеся з такою проблемою.


0

Я не думаю, що будь-яка з відповідей досить точна. Згідно з Вікіпедією, ендіантність - це порядок байтів, що містять слово.

Давайте візьмемо 4 байти та інтерпретуємо їх як int. Одна небагато ендіанська система байтів буде інтерпретуватися справа наліво, а віце-верка на великій ендіанській системі. Очевидно, важливо домовитись, з якою метою трактувати інт.

Дозволяє трохи зменшити масштаб сучасних мережевих протоколів, які можуть використовувати json або xml. Жоден із цих форматів не передасть int як 4 байти. Вони передадуть дані у вигляді тексту, який буде проаналізований як int на стороні, що приймає.

Отже, зрештою, ендіанство не має значення при використанні json або xml. Нам все ще потрібно використовувати великий ендіан для заголовків tcp, тому його називають порядком мережевих байтів, але більшості програмістів не потрібно щодня возитися з ними.

Найбільш широко використовуваним кодуванням сьогодні є utf-8, який щасливий також бути несприйнятливим до проблем, пов'язаних з витримкою .

Тому я б сказав так. Безпечно ігнорувати ендіанси при використанні текстових форматів, переданих за допомогою utf-8.


два голоси проти і жодних коментарів. Чудово.
Есбен Сков Педерсен

1
Я не був прихильником, але ця відповідь, як видається, ігнорує / відхиляє цілком коректне питання. Тільки тому, що деякі протоколи є текстовими, не означає, що всі протоколи повинні бути.
Пітер Грін

2
Я підтримав це, оскільки це стосується того факту, що формат корисної навантаження не має нічого спільного з базовими протоколами. Деякі люди просто люблять копатися у складених проблемах.
Зденек,

0

Великі ендіанські системи, здається, вже виходять. Багато традиційних уніфікатів використовували великі ендіани, але вони роками занепадають на користь linux на x86.

рука є бієндіанським, але великий ендіанський варіант, здається, рідко зустрічається.

мип існує в обох варіантах. Зрозумілий варіант великого ендіану в основному спостерігається на мережевих додатках (з історичних причин в Інтернет-протоколах зазвичай використовується великий ендіан).

ppc був традиційно великим ендіаном, де деякі частини підтримують обох ендіан, але, схоже, IBM зараз підштовхує маленький ендіанський режим для 64-розрядних ppc (вони нещодавно відсунули порти ppc64el в Debian і Ubuntu).

Спарк, як правило, великий ендіан, але, схоже, знову в занепаді.

Якщо ви реалізуєте існуючий протокол, то, очевидно, ви повинні дотримуватися його специфікацій. Якщо ви хочете, щоб IETF поблагословив ваш новий протокол, то великий ендіан, швидше за все, буде простішим, тому що це те, що вони вже використовують у своїх існуючих протоколах, але IMO для нового дизайну протоколу «greenfield» маленький ендіан - це шлях.

Ви можете або вводити макроси з самого початку, які не матимуть ніяких функцій для маленьких ендіанських систем, або ви не можете турбуватися, поки / доки вам не доведеться підключитись до великої ендіанської системи.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.