Кратко

  • В RFC 1013 первое сообщение клиента X11 начиналось с байта: восьмеричное 102, прописная B, означало старший байт первым; восьмеричное 154, строчная l, младший байт первым. Обычные 16- и 32-битные поля следовали этому выбору клиента.
  • Изображения передавались в форматах, заданных сервером, включая его порядок байтов для пикселей. Сервер при необходимости переставлял байты обычных числовых полей; клиент готовил байты картинки по требованиям сервера.

Программа на одной рабочей станции хочет открыть окно на экране другой. Она передаёт ширину, высоту, номера ресурсов и команды рисования. Если процессоры размещают байты многобайтового числа в противоположном порядке, получатель может прочесть другую ширину. Провод не виноват: он доставил всё до последнего байта. Договариваться надо было о том, с какого конца начинать число.

Опубликованный в июне 1987 года RFC 1013 представлял альфа-обновление протокола X версии 11. Удалённый клиент мог работать поверх любого надёжного потока байтов; при TCP сервер дисплея N принимал соединения на порту 6000 плюс N. Первым байтом клиент объявлял порядок для 16- и 32-битных величин. В документе значения 102 и 154 записаны в восьмеричной системе. Они соответствовали прописной B и строчной l ASCII, то есть старшему или младшему байту первым. Буква служила не приветствием, а инструкцией по чтению.

Для обычных полей порядок устанавливал клиент. Сервер при необходимости переставлял байты под этот выбор и возвращал многобайтовые величины в том же порядке, кроме прямо оговорённых случаев. Приложению не требовалось выяснять, как процессор у дисплея хранит числа в памяти. Сервер брал на себя перевод. Одного символа в начале было достаточно, чтобы поручить эту работу конкретной стороне.

С изображениями власть переходила к дисплею. Битовые и пиксельные изображения подчинялись форматам сервера. В ответе на установление соединения он сообщал image-byte-order, единицу и выравнивание строк bitmap, поддерживаемые форматы pixmap. Для XYFormat порядок относился к каждой единице строки, для ZFormat — к каждому значению пикселя. Клиент с иным собственным порядком должен был переставлять байты картинки. Хозяин экрана указывал, как упаковать картинку для его оборудования.

Такая асимметрия задавала конкретный риск при реализации. Программа могла верно передать размеры окна и всё же отправить пиксели по правилу для команд. RFC указывал, кто должен выполнять каждое преобразование. Не требуется выдумывать поломанный исторический экран: ошибка видна из двух разных инструкций. Удачно разобранный запрос на окно ещё не проверяет следующую за ним картинку.

После начального байта клиент посылал ожидаемую версию протокола, название способа авторизации и его данные. Сервер сообщал свою версию, результат подключения и, при согласии, сведения о ресурсах и форматах изображения. Основной текст не назначал единый перечень допустимых механизмов авторизации. В нашей истории важна последовательность двух решений: первая буква учит сервер читать команды, ответ сервера учит клиента собирать изображение.

Протокол не делал все компьютеры одинаковыми. Он раздал разные обязанности: сервер переводил обычные значения на язык клиента, клиент упаковывал пиксели на языке дисплея. Общее окно держалось на этом распределении, а не на надежде, что байты сами найдут правильный порядок. Перед первой картинкой обе стороны знали, кому придётся переворачивать числа.