10. Реализация протоколов

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

Первый шаг в понимание что же надо реализовать. Имеется три базовых типа протоколов:

1.       Стандартный – эти протоколы относятся к Интернет стандартам.

2.       Пользовательский – пользовательские протоколы используются, когда отсутствует нужный протокол.

3.        Разработчика – это протоколы, предназначенные для общения с собственными системами или оборудованием. Протоколы разработчика – это пользовательский протокол, разработанный программистом, а вы общаетесь с ним.

Большинство протоколов общаются, с помощью текста, и если только у вас нет особых причин, то и вы тоже должны поступать также.

Первым шагом построения клиента или сервера – это понять протокол. Для стандартных протоколов это может быть сделано с помощью чтения RFC. Для пользовательских протоколов вы его должны сами разработать.

Большинство протоколов используют просто текст. Общение означает посылку команд и получение ответов, а возможно и данных. Текст делает протокол более простым для отладки и позволяется использовать любые языки программирования и операционные системы.

Код состояния традиционно трехзначный номер. Не имеется стандарта на определение кодов состояния, но многие протоколы используют де-факто следующие соглашения:

·        1xx - информационные

·        2xx - успешные

·        3xx – временные ошибки

·        4xx – постоянные ошибки

·        5xx – внутренние ошибки

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

10.1.1. Простой текст (plain text)

Простой текст (plain text) означает, что все команды (commands) и ответы (replies) используют только 7-битный код ASCII. Если передача данных в откликах (responses) допустима в двоичном виде, то почти все команды протокола и ответы используют простой текст. Двоичный код никогда не должен использоваться в командах и ответах, если на это не будет веских оснований.

Использование простого текста упрощает отладку и тестирование. Это также означает переносимость между операционными системами и языками программирования.

10.1.2. Команды (commands)

Команда это текстовая строка, которая посылается клиентом серверу для запроса информации или выполнения определенных действий. Примеры команд: HELP, QUIT, LIST.

Команды могут содержать дополнительные параметры, разделенные пробелами.

Пример:

GET CHARTS.DAT

GET - это команда, а CHARTS.DAT – это параметр.

10.1.3. Ответы (reply)

Ответы – это короткий ответ на посланную команду. Ответ содержит информацию о состоянии – успешно ли ошибка, и иногда содержит небольшое количество данных.

Например, если команда GET customer.dat, вернет ответ 200 OK, это будет означать, что команда воспринята и будет обработана. Ответы обычно состоят только из одной строки, но могут состоять и из нескольких строк.

10.1.4. Отклики (response)

Отклик – это часть данных, которая возвращается в ответ на команду. Отклики дополнительны и не присутствуют во всех команда. Отклики посылаются после ответа, для распознавание правильный ли ответ получен и какой формат этого отклика.

Отклики могут быть текстовыми или двоичными. Если отклик текстовый, то обычно этот отклик в формате RFC откликов.

10.1.5 Переговоры (conversations)

Большинство протоколов аналогичны переговорам. Некоторые очень просты, а некоторые нет, но обычно они все равно в простом текстовом формате.

Переговоры означают следующую структуру:

1.       отправка команды

2.       возврат состояния

3.       дополнительные данные отклика

Вернем обратно к примеру получения почтовых кодов, в котором обмен выглядит следующим образом:

Client: lookup 37642 77056

Server: 200 Ok

Server: 37642: CHURCH HILL, TN

Server: 77056: HOUSTON, TX

Server: .

Разделив на отдельные куски, разговор будет выглядеть так:

Команда:

Client: lookup 37642 77056

Ответ:

Server: 200 Ok

Отклик:

Server: 37642: CHURCH HILL, TN

Server: 77056: HOUSTON, TX

Server: .

Каждая из этих частей будет объяснена ниже.

10.2 RFC - определения

В настоящем нет действующих стандартов для терминов, обсуждаемых в данной главе. Тем не менее, эти термины базируются на квази-стандартах, на которых работают все тексто-ориентированые RFC протоколы.

Единственное значимое исключение- это протокол POP3. Это мистерия, почему разработчики решили идти своим путем, вместо пути RFC. Протокол POP3 в реальности очень ограничен и не предлагает нужной дополнительной функциональности к протоколу. Это обычная диверсия.

Протокол IMAP4, который был предложен как наследник POP3, продолжил эту порочную практику и так же использует не стандартный механизм.

 После этих двух упоминаний, текстовый протокол все еще остается квази-стандартным. Этот квази-стандарт общий путь посылки команды и получение ответов и откликов.

10.2.1. RFC - коды состояния

Коды состояния RFC имеют следующую форму:

XXX Status Text

Где XXX это цифровой код в диапазоне 100-599.

Трехзначный цифровой номер означает ответ, который в ран-тайм, служит для определения результата выполнения команды. Обычно присутствует дополнительный текст, показываемый пользователю или для отладки. В этом случае, обычно используется английский язык, но может быть и локализован, если будет удовлетворять 7-битному коду ASCII. В некоторых случаях, когда данные короткие, данные возвращаются в дополнительном текстовом поле. В этих случаях данные все рано должны быть 7-бит ASCII, но протокол сам определяет язык и ограничения форматов. В большинстве случаев, эти данные языко-независимы (language neutral). Например, команда "TIME", возвращает "15:30" в дополнительном текстовом поле.

Пример RFC ответа:

404 No file exists

404 это цифровой отклик и "No file exists" это дополнительное текстовое сообщение. Только код 404 должен быть интерпретирован программой и код 404 должен быть точно определен протоколом именно для этого. Текстовое сообщение обычно используется для отладки, ведения логов или для показа пользователю. Текстовое сообщение может иметь различные формы, от реализации к реализации и может быть локализировано на другие  языки. Языки которые не соответствуют требованиям кода 7-бит ASCII должны быть транслитеризированы в английские символы.

Цифровая часть может быть назначена любым значениям. Тем не менее существует общее соглашение:

·        1xx - информационные

·        2xx - успешные

·        3xx – временные ошибки

·        4xx – постоянные ошибки

·        5xx – внутренние ошибки

Цифровые коды, заканчивающие на 00, то есть 100, 200, и так далее резервированы для общих ответов, которые не имеют специального значения связанного с ними. 200 наиболее часто с "Ok".

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

Пример такого ответа:

400-Unknown Error in critical system

400-The server encountered an error and has no clue what caused it.

400-Please contact Microsoft technical support, or your local

400-tarot card reader who may be more helpful.

400 Thank you for using our products!

10.2.1.1. Примеры

Здесь пример некоторых кодов состояния, полученные от HTTP протокола. Как вы видите они относятся к разным категориям по первой цифре.

200 Ok

302 Redirect

404 Page not found

500 Internal Error

10.2.2. RFC – ответ (reply)

RFC ответ, возвращает код состояния.

10.2.3. RFC – отклик (response)

RFC отклик это текстовый ответ, ограниченный строкой с одной точкой в начале. Если данные содержат строку, которая содержит точку, то она перекодируется в две точки перед передачей, и обратно преобразовываться в одну при приеме.

RFC отклики очень применимы, когда заранее неизвестно количество возвращаемых данных. Это используется в HTTP, Mail, News и других протоколах.

Методы Indy, которые поддерживают RFC отклики – это Capture (для приема) и WriteStrings (для передачи).

10.2.4. RFC - транзакции

Транзакция RFC это общение, которое состоит из команды, ответа и дополнительного отклика, все в формате RFC. Обработчики команд и другие части Indy построены на транзакциях RFC.

10.3. Класс TIdRFCReply

TIdRFCReply обладает возможностью посылки и приема RFC ответов. TIdRFCReply имеет три основных свойства: NumericCode, Text и TextCode. NumericCode и TextCode взаимно исключающие. TextCode – свойство, которое управляет такими протоколами, как POP3 и IMAP4.

Для генерации ответа, установите свойство NumericCode (или TextCode) и дополнительно введите текст в свойство Text. Свойство Text типа TStrings позволяет многострочные ответы.

TIdRFCReply имеет методы для записи форматированных ответов, и также для разбора текста в TIdRFCReply.

TIdRFCReply используется для посылки ответов на команды, и также для свойств ReplyException, ReplyUnknown и Greeting properties класса TIdTCPServer.

10.4. Класс ReplyTexts

Цифровой код в ответе обычно уникален для каждой ошибки. Например, протокол HTTP  использует код 404 для "Resource not found". Многим командам разрешено возвращать код 404 как ошибку, но код 404 всегда должен означать одну и туже ошибку. Для преодоления дублирования текстов для ошибки 404 класс TIdTCPServer имеет свойство ReplyTexts.

Свойство ReplyTexts – это коллекция экземпляров TIdRFCReply, которые могут быть обработаны, как в ран-тайм, так и в дизайн-тайм. Свойство ReplyTexts используется для обработки списка текстов, которые связаны с цифровым кодом. Когда свойство TIdRFCReply используется в TCPServer, который имеет цифровой  код, но не имеет текстовой части, Indy просматривает в ReplyTexts и использует строку от туда.

Вместо включения текста, в каждый ответ 404 посмотрите ниже:

ASender.Reply.SetReply(404, 'Resource Not Found');

Затем может использоваться следующий код:

ASender.Reply.NumericCode := 404;

Перед тем, как Indy посылает ответ, она сначала устанавливает свойство Text из найденного в ReplyTexts. Это позволяет хранить все тексты ответов в одном месте, позволяя легко управлять ими.

10.6. Определение пользовательского протокола

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

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

При определении протокола, должны быть сделаны следующие решения:

·        Текстовые или двоичные команды? Пока нет особых требований, используйте текстовые команды. Текстовые команды проще для понимания и для отладки.

·        TCP или UDP? Это определяется от требований к протоколу. Изучите все характеристики и решите с осторожностью. В большинстве случаев TCP правильный выбор.

·        Порт – каждому серверному приложению требуется выделенный порт для прослушивания. Порты ниже 1024 резервированы и никогда не должны использоваться, кроме реализации протокола, которому уже назначен порт ниже 1024.

После определения команд, также должны быть определены ответы и отклики.

10.7. Симуляция другой стороны (Peer Simulation)

Традиционно естественный путь построения клиента и сервера – это сначала построение сервера, а затем клиента или построения их параллельно. Но Indy имеет возможность построить клиент или сервер, отдельно друг от друга. В некоторых случаях, один может быть построен без необходимости доступа к другому.

10.8. Протокол получения почтового кода

В данной главе более подробно обсуждается Протокол получения почтового кода, который был представлен  ранее в его клиенте. Сам сервер будет обсужден позже.

Проект был разработан так, чтобы быть как можно более простым. Сервер получения почтового кода (Zip код в Америке) позволяет клиенту запросить город и штат, к которому относится почтовый код.

Примерные данные, которые использует сервер, относятся к американским почтовым кодам, которые у них называются zip коды. Протокол может обрабатывать и другие коды, но американские коды уже заложены в демо программу.

Для тех, кто находится за пределами Соединенных Штатов Америки и не знаком с их системой,  zip это почтовый код в США, который указывает регион доставки. Zip коды цифровые и состоят из 5 цифр. Zip коды могут также содержать дополнительные четыре цифры в формате 16412-0312. Данный тип кодов получил название Zip+4. Четыре дополнительные цифры уточняют локальную зону доставки и не требуются для определения города.

При создании протокола были приняты следующие решения:

·        Все команды текстовые

·        Транспорт TCP

·        Порты: 6000. Порт 6000 это наиболее часто используемый номер в тестовых примерах Indy. Это не имеет значения.

Протокол поддерживает следующие команды

·        Help – получение справки

·        Lookup <почтовый код 1> < почтовый код 2> ... – запрос информации

·        Quit – отсоединение от сервера

При разработке протокола, полезно знать ключевые протоколы, такие как - NNTP, SMTP и HTTP и использовать их как модель. Исключая POP3 и IMAP4. Поскольку это плохой пример построения протоколов.

10.8.1. Команда Help

Команда Help очень часто используемая команда и редко применяемая в автоматических клиентах. Данная команда наиболее пригодна для использования человеком, который или тестирует, или напрямую работает с сервером. Почти все серверы реализуют данную команду.

Команда Help полезна для вывода справки о командах сервера и их возможном применении.

Для нашего протокола, сервер отвечает кодом 100, плюс сопроводительный текст.

10.8.2. Команда Lookup

Команда lookup принимает один или несколько почтовых кодов для поиска и возвращает название города и штат. Данные возвращаются в формате RFC откликов. Если код не найден, то отклик не возвращается (но если судить по примеру это не так, возвращает пустой отклик – строка с точкой). Код ответа "200 Ok".

Пример:

lookup 37642 16412

200 Ok

37642: CHURCH HILL, TN

16412: EDINBORO, PA

.

Даже если код не найден, то возвращается ответ "200 Ok".

lookup 99999

200 Ok

.

Мы приняли такое решение. Если бы сервер мог воспринимать только один параметр, то можно бы было отвечать кодом 200, и если не найден, то кодом 4XX. Но протокол может возвращать часть для правильных данных, поэтому было решено всегда возвращать код 200.

При частично правильных данных и ответ:

lookup 37642 99999

200 Ok

37642: CHURCH HILL, TN

.

Если бы протокол возвращал код ошибки, то частичные данные были бы проигнорированы. Данное решение позволило серверу отвечать и на частично правильные запросы, без генерации ошибки.

10.8.3. Команда Quit

Команда quit является прямым приказом серверу прекратить сессию и отсоединиться.

Почтовый протокол выдает многострочные ответы. Это не определено самим протоколом. Любые RFC ответы могут быть как однострочными, так и многострочными. Indy обрабатывает оба типа ответов автоматически.

 

Hosted by uCoz