Как стать автором
Обновить

Комментарии 74

Если не копипаст, то отличная статья!
Не… это не копипаст
Прошу прощения, «AT-команды», ATZ — это уже команда (сброс модема, кажется).
Вы несомненно правы;)в 3 ночи малость ошибся;)
Очень интересная справка (всё же не совсем статья). Всё разжевал «для нубов», это несомненный плюс.
Будет супер если ты будешь писать мини-цикл статей про различные типы проектирования. Хотя бы про данные.
Хотелось бы всё же почитать про проектирование протоколов на доступном языке. Было бы куда отсылать интересующихся и не очень наученных по данной теме.
Весьма интересная статья.
Автору посоветую рассмотреть серию протоколов Modbus, весьма популярный в АСУиТП набор протоколов, хорошо задокументированный. Правда есть у него один «бзик», порожденный его массовостью. Почти каждая контора, которая выпускает на рынок желехку поддерживающую этот протокол, говорит что Modbus то стандартный, но вот мы чуток его под себя приспособили.
Наиболее частые приспособления — введение новых типов команд (как правило вместе с новыми типами данных), ну такие изменения еще как-то предусмотрены в документации на протокол, но иногда новаторы изменяют значения зарезервированных команд; изменение правил упаковки данных (тот самый порядок следования байт); изменение привязки типов к диапазонам адресов — ну тут вольница, в принципе, я уже даже не обращаю на такие вещи внимания.
пните откуда начинать читать;)
ru.wikipedia.org/wiki/Modbus — хотя бы вот отсюда))
Вообще пробежался по статье в вики, уж не знаю как тогда фирма называлась, у меня Modicon ассоциируется с контороллером технологическим, производимым фирмой Shnider.
Пока писал ответ, искал общедоступные источники, вот более адекватный источник — www.modbus-ida.org/specs.php
К сожалению в статье на вики практически не описана разновидность Modbus ASCII.
Еще стоит упомянуть протоколы типа IEC 101, 102, 104. От работы с этими протоколами остались не самые лучшие воспоминания. Довольно большая избыточность и сложность реализации.
хех, я думал разговор пойдет о джабберах и рпс а тут модбас… довайте тогда с i2c начнем чтоле)
ну честно говоря статья задумывалась как статья о кастомных протоколах.
Ну простите асушника, ни о чем другом думать не могу))
Хотя в качестве «ликбеза», думаю стоит знать о таких вещах знать. Часто достаточно на форумах вижу, ребята пытаются пару чисел передать, им советуют всякие кошмары наворачивать. Я бы понял, если бы проект надо было масштабировать, эту работенку проектом-то назвать трудно.
А тут вроде как и довольно хорошо описанный и ставший стандартом протокол, и сырцов навалом, да и просто софта законченного.
И в качестве учебного материала очень хорош, довольно прост, легко можно его расширить, прикрутить новые «фичи». В принципе я так и поступил в свое время, когда надо было синхронизировать две системы, просто на основе сырцов драйверка собрал и сервер и клиент, добавил некоторые поля, работает по сию пору, и не чихает. Рядом стоят тачки наших коллег, взаимодействие через OPC, регулярное ездят с DCOM шаманить.
Спасибо за статью. Было бы интересно если бы автор написал статью об особенностях проектирования протокола для приложений реального времени, причем где нельзя доверять клиенту. Например виртуальные трехмерные среды с центральным сервером.
про подобное напишу с радостью, но если можно чуть поподробнее объясните что именно вы имеете в виду;)
Интересно как можно с помощью протокола хотябы немного разгрузить сервер от вычислений.
Приведу пример. Предположим что разрабатываем виртуальный мир. Есть сервер, есть клиенты.
Клиентам доверять нельзя. То есть все вычисления изменений мира приходится переносить на сервер.
А клиент тогда только занимается приемом ввода пользователя, передачей этих данных серверу, приемом обновленных данных об среде и отображением этих данных пользователю.
Это простой способ. Но его проблемой будет высокая нагрузка на сервер и некоторая задержка на клиенте.
Если бы клиенту можно было доверять, то тогда сервер мог бы достаточно большую часть вычислений передать ему.
Соответственно при проектирования подобного приложения (трехмерный чат, ммо игра) встает проблема, доверия клиенту, и баланс нагрузки по обсчету виртуального мира между сервером и клиентом. Частично мне кажется что эту проблему можно решить с помощью правильно спроектированного протокола. Вот об этом хотелось бы и почитать.
на досуге подумаю, может что и напишу дельное по этому поводу;) не спорю, задача крайне интересная;)
Интересная, но практически нереальная. Всё равно найдутся умельцы, которые ваш протокол раскусят и будут, извините, гадить. Проверено годами существования MMORPG-игр. Выход в таком случае только один — постоянно модифицировать протокол. Что, имхо, геморно не только для программиста, так и для клиентов.
А если перестать думать что вся информация одинаково ценна, то можно сильно соптимизировать теряя некритичные данные.
Может interreality.org/wiki/VipDocumentation чем-то то поможет? Они какие-то такие протоколы делали для похожих ситуаций.

Перенес пост в блог «разработка»
Очень понравилось, хорошо написано. Хочется узнать о шифровании\ дешифровании данных и защите протоколов. Автору большое спасибо!
НЛО прилетело и опубликовало эту надпись здесь
НЛО прилетело и опубликовало эту надпись здесь
Подобные руководства никогда не писал, поэтому такие ошибки есть;) Постараюсь ответить в обсуждении поста на подобные непонимания.

Рукопожатие нам нужно, чтобы понять а туда ли мы вообще будем слать данные и жив ли сервер. То есть это элементарная проверка на валидность и адекватность получателя.
НЛО прилетело и опубликовало эту надпись здесь
А откуда в таком случае будет гарантия что Вы шлёте данные именно туда куда хотите? А при стадии рукопожатия, можно хотя бы определить, что сервер вроде бы отвечает на приветствие ожидаемым для нас образом.
НЛО прилетело и опубликовало эту надпись здесь
нет нельзя. а вдруг это сервер со сходным ответом на запросы? просто считает он другое,
НЛО прилетело и опубликовало эту надпись здесь
Да сделайте рукопожатием в качестве рукопожатия обмен MD5 хэшами от двух каки-нибудь «особенных» строк, или сгенерируйте один раз две случайные последовательности, символов в 30 и используйте их в качестве рукопожатия… сомневаюсь, что ещё какой-то сервер будет использовать точно такое же рукопожатие ;)
прошу прощения за тавтологию в самом начале комента…
НЛО прилетело и опубликовало эту надпись здесь
НЛО прилетело и опубликовало эту надпись здесь
тоже вариант, но ИМХО отдельная фаза протокола не так страшно (ведь она выполняется один раз за весь сеанс связи, а он может состоять из команд так 500).
НЛО прилетело и опубликовало эту надпись здесь
Угу. И так уже две версии есть из-за того, что Google затянул с открытием своей версии, нефиг порождать ещё сущности.

Передавать что-нибудь, что не вписывается в ProtoBuf/Thrift требуется очень редко, а потери в скорости если использовать JSON/XML/etc огромны.
ну надо как минимум помянуть названия N+1 реализаций RPC, так и не захвативших мир =)
а в плане тэговых структур модный нынче гугловый protobuf и различные сериализаторы объектов встроенные в языки.
Это не всегда хорошо. Оно очень удобно, я не спорю. Но когда нам нужна скорость и возможность реализации протокола на железе… тогда все эти универсальные протоколы идут практически сразу лесом.
Мы вроде о сетевых протоколах? Ну тогда все неуниверсальные протоколы идут в лес. К огромному сожалению «не лесом», а именно «в лес». То есть люди делают какую-то свою реализацию, которая «типа быстрее», потом через год её нужно «чуть-чуть подправить», через два «немного расширить» и в результате лет через 5-7 вы получаете нечто, что сложнее и медленнее чем protobuf/thrift.
Оно все конечно и так бывает. Но при разработке каких-то сложных комплексов обычно сначала проектируют (с учетом всего что можно будет добавить), а только потом уже делают протокол. И опять же железяку (я имею в виду некий кастомный аппарат, который также входит в этот комплекс, например видео-камеру) очень тяжело понимать/отдавать универсальные протоколы.
jfyi: у нас есть железяка, для сбора данных с других железяк.
За годы эволюции её начинки, сегодня в ней живёт xmpp-клиент.
Я честно рад за вашу железяку. Но почему-то у нашей оборонки подобных железяк очень мало;(
на счет «в железе» — из protobuff вроде и C++ генерится. Неужели его нельзя запихнуть в нужное железо?
те железяки с которыми я работал в свое время этого не умели
своё время — эт да.
Но сейчас-то другое время.

Впрочем, для не сильно сложных протоколов, не должно составлять большого труда переписать куски кода с C++ на С, для встраивания в железяку, если для этой железяки нет своего C++ компилятора.
По моим ощущениям, это всёранво будет выгоднее, чем писать и поддерживать реализации провтокола на обоих концах.
это свое время было год назад;)

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

Вы заранее закладываетесь на провал?
Нет. По опыту работы на оборонку (а именно из этого опыта написана статья) могу сказать что те комплексы которые мы разрабатывали (при мне один успешно сдали и второй начали) успешно вписывались в разработанные нами протоколы (понятно дело с подпиливанием, но крайне минимальным).
Да вписать-то можно что угодно и во что угодно. Вопрос «а можно ли...» в программировании почти никогда не встаёт. Тут другой вопрос: «а чем это нам грозит?».

Я не знаю сколько лет прожили ваши комплексы, но то, что они работают по спецификации на момент сдачи заказчику ничуть не удивляет. Что с ними будет через 10-20-30 лет — вот об чём речь. Какой-нибудь B-52 полувековой давности до сих пор в строю!
эммм… через 10-20-30 лет будет с ними тоже что и сейчас… они сданы после ГосИспытаний, в них уже могут быть только минимальные исправления
Ну тогда, по крайней мере, понятно почему максимум на что способна стомиллионная Россия — это разобраться с пятимиллионной Грузией и то со скрипом…
Не совсем из-за этого. Там много технических факторов. Один из немаловажных это требование использовать Эльбрусы и МСВС.
Скажите, а у Вас большой опыт использования МСВС? Можете поделиться подводными камнями?
Как раз сейчас работаю в первом проект под нее, хочется знать, чего ждать впереди из косяков.
самый главный подводный камень это сама МСВС;)
с точки зрения разработки там самый главный косяк — это хитрая очистка памяти при вызове например delete или free(). При этом все что вы освободили будет перезаписано нулями. Так что не советую удалять большие куски памяти, лучше их попытаться переиспользовать.
Еще не маловажный косяк МСВС — это софт, который там стоит (во всяком случае, в той версии где работал я было так). Для разработки (вернее чтобы что-нибудь поправить, полностью под ней сидеть невозможно) лучше всего редактор в mc :), так как все остальное крайне старо (например KDevelop2).
Я как-то писал протокол обмена данными для системы распределенных вычислений. Протокол должен был обеспечивать связь клинета(вычислителя) и центра вычислений(координатор действий и сборщик результатов).
У меня протокол был в виде классов с примерно таким интерфейсом
class proto_command {
...
virtual void * pack() const = 0;
};

class proto_hello: public proto_command {
struct {
const char[5] = "Hello";
} cmd_struct;

char * pack();
char * unpack();

};


Все было сложнее, но суть, думаю, понятна — каждая команда в отдельном классе.
Вот, собственно, функции упаковки и распаковки спасали от всяких переворачиваний. Как пакуем, так и распаковываем.

p.s. Не писал на плюсах уже много лет, так что если синтаксически что-то не так — извиняйте =)
Да, это один из способов реализации. Честно говоря мне удобнее пользоваться методами внутри одного класса (это позволяет в любой момент заменить разбор на любой другой просто заменой файла с классом), а обращение к разборщику реализовывать через базовый класс.
> Это означает, что размер любой структуры всегда будет кратен 4 (если размер структуры был 14, то в конец
> допишутся 2 ничего не значащих байта и размер станет равен 16).

Дополню: не обязательно в конец. Если внутри структуры идут, например, байтовые данные, они тоже выравниваются. Идея в том, что каждое поле структуры должно быть варавнено на 2/4 и т. д. байта.
вы правы
Однозначный плюс этому обзору, всё понятно и доходчиво разложено по полочкам. Автору спасибо, была бы возможность в карму бы добавил плюс. Жду с нетерпением новых статей.
ээ, могу ошибаться, но имхо, одним из первых важных моментов в описании сетевого протокола будет хотя бы упоминание свойств и возможностей нижележащего протокола, таких как есть ли гарантированная доставка, коррекция ошибок и т. д. простой пример — реализация того, что описывает автор на основе удэпэ и тисипи будет существенно отличаться.
Не спорю, но если писать про все это, то можно дописать и до книги средних размеров.
Не понял, «Вопрос-ответ» не может использовать в качестве упаковки дынных структыры или теги? Зачем смешиваете логику работы и представление данных? Разе в HTTP 1.1. Get+XML это не «вопрос-ответ» с тегами? Это тоже самое что говрить, что обощи бывают трёх видом — красные, круглые и вкусные.
Короче говоря трудности с терминологий и какая-то мешанина.

Тогад уж пишите, что по логике обмена протоклы бывают:
1) «ЗАпрос-ответ» (я не «ВОпрос-ответ»), кода одна из сторон обмена (ведомая/slave) может передавать данные только по запросу второй (ведущей/мастер/host). Это самый простой с точки зрения реализации тип обмена, но недостаком имеет длительное время реакции при большой кол-во аобнентов в сети (пока всех опросишь).
2) асинхроные, когда обе стороны равноправны и могут начать обмен в любой момент времени. Достоинством имеет минимальное время реакции, но необходимо решать вопросы синхронизации состояний у абонентов и коллизий при некоторых физический протоколах.
3) ВременнЫе окна (Time frames). Фактический смешаный типа, когда одна из сторон управляет обменом и может предоставлять право обмена другим абонентам и/или группам. Очень популярный тип, широко применяется при радиобмене — от GSM до WiFi. Позволяет сохранить приемлемое время реакции и не потерять возможность управления сетью. Но всё равно нужно решать проблеммы коллизий для некоторых физических уровней.

Далее протоклы подразделяются по типу синхронизации потока данных:
1) Полностью асинхронные протоклы. Целиком зависят от надёжности нижележащего уровня. При искажении данных нсами воосстановить синхронизацию не могут. Соответсвенно могут работать поверх TCP/IP, но не на обычном последовательном порту.
2) Протоколы с временнОй синхронизацией. Синхронизируются по паузам между пакетами, либо возлагают процедуру синхронизации на протоколы более низких уровней.
3) Самосинхронизирующиеся протоколы. Как правило начало каждой посылки (пакета/кадра/фрейма) обозначается специальным маркером, который не может встречаться в данных, что реализуется, обычно, при помощи т. н. байт-стафинга или бит-стафинга. В простейшем случае маркером может служить символ перевода строки. В случае ошибки в потоке данных, будет потерян один блок данных, а со следующего блока синхронизация будет восстановлена. Самая популярная группа протоколов. (Большинство промышленных протоколв).

Протоколы могут иметь контроль целостности данный и/или коррекцию ошибок или не иметь.

1) Если протокол обладается контролем целостности (обычно при помощи контрольной суммы дла каждого блока данных), то принимающая сторона может определить факт искажения данных. (IP, UDP, TCP)
2) Если протокол обладает возможностью коррекции ошибок, то ошибки и искажения данных в некоторых пределах могут быть скорректированы принимающией стороной на основании избыточной информации передавайемой совместно с данными. (Форматы записи компкат и жёстких дисков, некоторые промышленные протоколы).
3) В противном случае, протокл полнотсью полагется на нижележащий уровень и в случае искажения данных, принимающая стороная об этом не узнает (например — HTTP).

Кроме того протоколы подразделяются по типу реакции на искажение данных:
1) Протоколы без повторов передачи. Полностью полагаются на нижелижещие уровни. В случае повреждения данных, передающая стороная не узнает, что данные не приняты.
2) Требующие подтверждения протоколы. Каждая порция данных требует подтверждения от принимающией стороны. В качестве развития, подтверждаться может не один пакет, а группа (как в TCP/IP). Если подтверждение не принято или получаен сигнал, о том, что данные приняты не верно, то передача может быть пвторена повторяется (а могут быть, как в UDP, просто отброшены неправильные данные).
3) Различные смешаные варианты. Например, данные могут повторяться с некоторым интервалом, в надежде, что одна из копий будет принята правильно.

Ещё можено делить протоклы по типу установления связи:
1) Перед началом сеанса связи происходит «рукопоажатие» (handshake) во время которого стороны договариваются о способе обмена данными и о возможности начала сеанса данных. Например — USB, IP, TCP.
2) «рукопожатие» не происходит — каждая сторона сразу готова принимать и передавать данные. Например UDP и множество промышленных протоколов.

Ваше деление по типу представления даных крайне не корректно. «структуры» обязательно имеют некий маркер позволяющий определить что это за структура и что за данные в ней. Для «теговых» протоколов таким маркером является теги. Вот и всё различие. Каким образом «вопрос-ответ» может быть типом представлния данных не понятно.
Немного смутило название статьи. «Проектирование сетевых протоколов» ассоциируется с моделью OSI и соответствующим уровнем. А в итоге оказалось, что речь идет совсем о другом.
Модель OSI — это миф. Забудьте про неё. Чем скорее вы про неё забудете, тем быстрее у вас появится возможность воспринимать информацию про то как реально работают сети — а там уже и до практического использования недалеко.
интерестно, откуда такая уверенность? то что интернет не совсем соответствует этой модели это факт, т. е. какие уровни пересекаються, а некоторых просто нет, но это еще не говорит о том что данная модель просто миф. модель ози/изо поможет избежать ошибок, сделанных при проектирования глобально сети, в будущем
Интернет не «не совсем соотвествует», а «совсем не соотвествует». Какие именно ошибки призвана исправить модель OSI — мне неведомо: в неё даже банальная VPN не вписывается. А вот вред от неё несомненен: она добавляет лишнюю сложность в и без того непростую картину. Она слишком сложна для половины случаев и недостаточно гибка для оставшихся.

Несколько напоминает описание мира с помощью четырёх-пяти-шести элементов (ну там «огонь», «воздух» и т. п.). Полезная вещь для всевозможных RPG, но бесполезная для химика или физика. А OSI модель даже и к RPG не приспособить.
Вполне вписывается и VPN туда, если рассматривать не с точки зрения функционала, а реализации. Где пакеты отправляемые на интерфейс просто заворачиваются в протокол транспортного уровня (TCP) и так далее. По сути завернуть пакет представляют собой обычные данные, которые на другой стороне развернутся и выйдут из виртуального интерфейса. Где тут не стыковка?
ЗЫ остальные уровни выше транспортного сливаются в один — прикладной.
Вполне вписывается и VPN туда, если рассматривать не с точки зрения функционала, а реализации.
А ничего что у вас получается два Network Layer'а если вы используете IPSEC, скажем, а если вы используете VTUN без UDP, то у вас между двумя этими слоями ещё и Transport Layer появляется. И если вы ещё и 802.11 используете при этом, то у вас ещё парочка Transport Layer/Network Layer окажутся под Data Link Layer'ом.

Если использовать OSI модель как набор «умных слов», то всё вкладывается, конечно, но какая от неё тогда польза? Нет в природе сетей соотвествующих модели OSI. Никогда не было, нет и не будет. Забудьте вы про своего сферического коня в ваккуме.
все плохо, хабр уже не тот, галактико вопасносте

1. Фактически нет разницы между тем, что вы называете «Вопрос-ответ» и «структуры». И то, и другое — обмен бинарными данными, просто формат может предполагать переменную длину структуры или фиксированную.

2. «Следовательно нам необходимо позаботиться об одинаковом значении этого параметра на сервере и клиенте.» Это жуткий совет, который скорее всего печальным последствиям. Нельзя ставить себя в зависимость от среды программирования. Если вы передаете бинарные данные, строго описывайте их в протоколе, а в программе соответствующие структуры обьявляйте с __attribute__((__packed__)) (это для gcc, естессно)

3. Как уже было сказано выше, про стадию рукопожатия — это лишнее. Путается красное с кислым. Есть понятие сценария взаимодействия, т. е. кто, как и когда посылает команды; в каком порядке; что происходит, если одна из сторон не отвечает и т. д. И еще отдельно есть понятие формата передачи данных: бинарные структуры, xml-блоки или нечто среднее; использование шифрования; повышение помехоустойчивости; архивирование. В общем, темы хотя и сильно взаимосвязаны, то стоило бы их отличать.

4. Что такое «теги+структуры» я не понял, чесно говоря. Сразу несколько ассоциаций появилось. Интересно было бы на пример реализации посмотреть, тогда, видимо, стало бы яснее.
Отвечу на этот коммент и заодно на коммент ниже.

1. Не совсем согласен. Все-таки те же AT-команды проще обрабатывать текстовым анализатором, нежели рассматривать их с точки зрения бинарных данных. По сути АТ-команды (не только они, но и аналогичные им протоколы) похожи на упрощенный SQL.

2. Я бы скорее посоветовал использовать резерв-поля на местах упаковки. Это дает возможность писать кросс-платформенно без кучи дефайнов под все компиляторы.

3. Я бы не стал категорично это утверждать. Можно смотреть с разных сторон.

4. Конкретный пример реализации привести не могу в силу некоторых причин, могу только сказать общую идею.
Предположим есть у нас сервер, обрабатывающий изображения. Он может принимать кучу разных изображений, с кучей разных параметров. Например для сжатого жпегом ему еще нужна степень сжатия, для индексного изображения нужна палитра, для географически-привязанных изображений нужна геоинформация (придумать можно много всего). Соответственно всяких разных комбинаций бесчисленное множество. Это можно описать как некий главный тег (который будет в себе содержать все параметры, которые общие для всех случаев), в его области данных будут лежать дочерние теги, такие как изображение (опять же если это индексное изображение, то у него будет дочерний тег — палитра), геопривязка, EXIF и так далее.
По приведённым описаниям разница между «Вопрос-ответ» и «Структуры» только в том, что один символьный, а другой — бинарный. В принципе, AT-команды модема вполне подпадают под описание структуры
смещение и длина некоторых полей могут также задаваться в структуре, но в основном используются изначально заданные смещения


Фразы «легко обрабатываются» и «не очень высокая скорость обработки» мне кажутся взаимоисключающими. Видимо, первая фраза подразумевает наличие готовых парсеров. Это стоит переформулировать более явно.
Как раз хотел написать об этом. К примеру TCP можно с легкостью отнести и к типу «Вопрос-ответ» и к типу «Структуры» и даже с некоторой натяжкой к «Теги+структуры». В TCP реализованы все приведенные вами атрибуты протоколов типа «Вопрос-ответ»: рукопожатие, пересылка данных, получение ответа и наличие id. Почему TCP относится к типа «Структуры» и так очевидно, вы это отметили в статье. А к «Теги+структуры» TCP можно отнести из-за наличия в нем поля Options, которое имеет неопределенную длину и структуру (кстати в статье вы это упоминаете под термином «нежесткая часть данных»).

Т. е. я хочу сказать, что такое разделение на типы слишком условно. Если вы проводите типизацию, то вы обязаны указать критерий типизации. Вы же проводите типизацию наобум что приводит к несоответствиям.
Видимо я не точно описал что я понимаю под «Вопрос-ответом». Я не имел в виду что оно должно вот так выглядеть. Я имел в виду что это некий упрощенный сильно ограниченный язык (как я писал выше похоже на упрощенный SQL). TCP относится к структурным (если вы внимательно читали, то видели заметку про возможные параметры переменной длины).

Также я вначале статьи указал что это чисто мое деление на типы, оно такое как его вижу я, поучавствовав в разработке сетевых и распределенных приложений.
«Классика» любых проектов предполагает наличие ЗАДАЧИ (ее не увидел), которая диктует ТРЕБОВАНИЯ (их тоже не видно), ограничения, допущения, условия, требуемые ресурсы. Вывод напрашивается: о чем же публикация.
Задача решена или нет? Как узнать? Если решена, то с каким качеством?
Вопросы можно продолжать…
Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации

Изменить настройки темы

Истории