Протокол своими руками. Создаем с нуля TCP-протокол и пишем сервер на C#

Ты в жизни не раз сталкивался с разными протоколами — одни использовал, другие, возможно, реверсил. Одни были легко читаемы, в других без hex-редактора не разобраться. В этой статье я покажу, как создать свой собственный протокол, который будет работать поверх TCP/IP. Мы разработаем свою структуру данных и реализуем сервер на C#.

Итак, протокол передачи данных — это соглашение между приложениями о том, как должны выглядеть передаваемые данные. Например, сервер и клиент могут использовать WebSocket в связке с JSON. Вот так приложение на Android могло бы запросить погоду с сервера:

И сервер мог бы ответить:

Пропарсив ответ по известной модели, приложение предоставит информацию пользователю. Выполнить парсинг такого пакета можно, только располагая информацией о его строении. Если ее нет, протокол придется реверсить.

Создаем базовую структуру протокола

Этот протокол будет базовым для простоты. Но мы будем вести его разработку с расчетом на то, что впоследствии его расширим и усложним.

Первое, что необходимо ввести, — это наш собственный заголовок, чтобы приложения могли отличать пакеты нашего протокола. У нас это будет набор байтов 0xAF, 0xAA, 0xAF. Именно они и будут стоять в начале каждого сообщения.

Каждый пакет будет иметь тип и подтип и будет размером в байт. Так мы сможем создать 65 025 (255 * 255) разных типов пакетов. Пакет будет содержать в себе поля, каждое со своим уникальным номером, тоже размером в один байт. Это предоставит возможность иметь 255 полей в одном пакете. Чтобы удостовериться в том, что пакет дошел до приложения полностью (и для удобства парсинга), добавим байты, которые будут сигнализировать о конце пакета.

Завершенная структура пакета:

XPROTOCOL PACKET STRUCTURE
 
(offset: 0) HEADER (3 bytes) [ 0xAF, 0xAA, 0xAF ]
(offset: 3) PACKET ID
  (offset: 3) PACKET TYPE (1 byte)
  (offset: 4) PACKET SUBTYPE (1 byte)
(offset: 5) FIELDS (FIELD[])
(offset: END) PACKET ENDING (2 bytes) [ 0xFF, 0x00 ]
 
FIELD STRUCTURE
 
(offset: 0) FIELD ID (1 byte)
(offset: 1) FIELD SIZE (1 byte)
(offset: 2) FIELD CONTENTS

Залишити відповідь

Ваша e-mail адреса не оприлюднюватиметься. Обов’язкові поля позначені *