В Indy реализовано
большинство распространенных протоколов. Но все равно бывают случаи, когда
требуется реализовать протокол самостоятельно. Основная причина в необходимости
реализации состоит в том, что нужный протокол отсутствует.
Первый шаг в понимание что же надо реализовать.
Имеется три базовых типа протоколов:
1. Стандартный –
эти протоколы относятся к Интернет стандартам.
2.
Пользовательский – пользовательские протоколы используются, когда отсутствует нужный
протокол.
3.
Разработчика – это протоколы,
предназначенные для общения с собственными системами или оборудованием.
Протоколы разработчика – это пользовательский протокол, разработанный
программистом, а вы общаетесь с ним.
Большинство протоколов общаются, с помощью текста, и
если только у вас нет особых причин, то и вы тоже должны поступать также.
Первым шагом построения клиента или сервера – это
понять протокол. Для стандартных протоколов это может быть сделано с помощью
чтения RFC. Для пользовательских протоколов вы его должны сами
разработать.
Большинство протоколов используют просто текст.
Общение означает посылку команд и получение ответов, а возможно и данных. Текст
делает протокол более простым для отладки и позволяется использовать любые
языки программирования и операционные системы.
Код состояния традиционно трехзначный номер. Не
имеется стандарта на определение кодов состояния, но многие протоколы
используют де-факто следующие соглашения:
·
1xx - информационные
·
2xx - успешные
·
3xx – временные
ошибки
·
4xx – постоянные
ошибки
·
5xx – внутренние
ошибки
Каждой ошибке обычно назначается уникальный номер, но
некоторые протоколы используют номера повторно и только предоставляют
уникальный цифровой номер для каждой команды, а не протокола.
Простой текст (plain text)
означает, что все команды (commands) и ответы (replies) используют только 7-битный код ASCII. Если передача данных в откликах
(responses) допустима
в двоичном виде, то почти все команды протокола и ответы используют простой
текст. Двоичный код никогда не должен использоваться в командах и ответах, если
на это не будет веских оснований.
Использование простого текста упрощает отладку и
тестирование. Это также означает переносимость между операционными системами и
языками программирования.
Команда это текстовая строка, которая посылается
клиентом серверу для запроса информации или выполнения определенных действий.
Примеры команд: HELP, QUIT, LIST.
Команды могут содержать дополнительные параметры,
разделенные пробелами.
Пример:
GET CHARTS.DAT
GET - это команда, а CHARTS.DAT – это
параметр.
Ответы – это короткий ответ на посланную команду.
Ответ содержит информацию о состоянии – успешно ли ошибка, и иногда содержит
небольшое количество данных.
Например, если команда GET customer.dat, вернет
ответ 200 OK, это будет означать, что команда воспринята и будет
обработана. Ответы обычно состоят только из одной строки, но могут состоять и
из нескольких строк.
Отклик – это часть данных, которая возвращается в
ответ на команду. Отклики дополнительны и не присутствуют во всех команда.
Отклики посылаются после ответа, для распознавание правильный ли ответ получен
и какой формат этого отклика.
Отклики могут быть текстовыми или двоичными. Если
отклик текстовый, то обычно этот отклик в формате RFC откликов.
Большинство протоколов аналогичны переговорам.
Некоторые очень просты, а некоторые нет, но обычно они все равно в простом текстовом формате.
Переговоры означают следующую структуру:
1. отправка команды
2. возврат состояния
3. дополнительные данные отклика
Вернем обратно к примеру получения почтовых кодов, в
котором обмен выглядит следующим образом:
Client:
lookup 37642 77056
Server:
200 Ok
Server:
37642: CHURCH HILL, TN
Server: 77056:
Server: .
Разделив на отдельные куски, разговор будет выглядеть
так:
Команда:
Ответ:
Отклик:
Server:
37642: CHURCH HILL, TN
Server:
77056:
Server: .
Каждая из этих частей будет объяснена ниже.
В настоящем нет действующих стандартов для терминов,
обсуждаемых в данной главе. Тем не менее, эти термины базируются на
квази-стандартах, на которых работают все тексто-ориентированые RFC протоколы.
Единственное значимое исключение- это протокол POP3. Это мистерия, почему разработчики решили идти своим
путем, вместо пути RFC. Протокол POP3 в реальности очень ограничен и не предлагает нужной
дополнительной функциональности к протоколу. Это обычная диверсия.
Протокол IMAP4,
который был предложен как наследник POP3,
продолжил эту порочную практику и так же использует не стандартный механизм.
После этих двух упоминаний, текстовый протокол все еще
остается квази-стандартным. Этот квази-стандарт общий путь посылки команды и
получение ответов и откликов.
Коды состояния 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!
Здесь пример некоторых кодов состояния, полученные от HTTP протокола. Как вы видите они относятся к разным
категориям по первой цифре.
200 Ok
302
Redirect
404
Page not found
500 Internal Error
RFC ответ,
возвращает код состояния.
RFC отклик это текстовый ответ, ограниченный строкой с
одной точкой в начале. Если данные содержат строку, которая содержит точку, то
она перекодируется в две точки перед передачей, и обратно преобразовываться в
одну при приеме.
RFC отклики очень применимы, когда заранее неизвестно
количество возвращаемых данных. Это используется в HTTP, Mail, News и других протоколах.
Методы Indy, которые
поддерживают RFC отклики – это Capture (для приема) и WriteStrings (для передачи).
Транзакция RFC это
общение, которое состоит из команды, ответа и дополнительного отклика, все в
формате RFC. Обработчики команд и другие части Indy построены на транзакциях RFC.
TIdRFCReply обладает возможностью посылки и приема RFC ответов. TIdRFCReply
имеет три основных свойства: NumericCode, Text и TextCode. NumericCode и TextCode взаимно
исключающие. TextCode – свойство, которое
управляет такими протоколами, как POP3 и IMAP4.
Для генерации ответа, установите свойство NumericCode (или TextCode) и
дополнительно введите текст в свойство Text. Свойство Text типа
TStrings позволяет многострочные ответы.
TIdRFCReply имеет методы для записи форматированных ответов, и
также для разбора текста в TIdRFCReply.
TIdRFCReply используется для посылки ответов на команды, и также
для свойств ReplyException, ReplyUnknown и Greeting
properties класса TIdTCPServer.
Цифровой код в ответе обычно уникален для каждой
ошибки. Например, протокол 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. Это позволяет хранить все тексты ответов в одном
месте, позволяя легко управлять ими.
Задача сетевого разработчика состоит не только во
взаимодействии с существующими системами, но часто и в создании собственных. В
таком случае требуется создание своего протокола.
Первым шагом построения клиента или сервера – это
разработка протокола. Для стандартных протоколов, это решается изучением
соответствующего RFC. Если же протокол не
стандартный, то должен быть определен.
При определении протокола, должны быть сделаны
следующие решения:
·
Текстовые или
двоичные команды? Пока нет особых требований, используйте текстовые команды.
Текстовые команды проще для понимания и для отладки.
·
TCP или UDP? Это определяется от требований к протоколу. Изучите
все характеристики и решите с осторожностью. В большинстве случаев TCP правильный выбор.
·
Порт – каждому
серверному приложению требуется выделенный порт для прослушивания. Порты ниже
1024 резервированы и никогда не должны использоваться, кроме реализации
протокола, которому уже назначен порт ниже 1024.
После определения команд, также должны быть определены
ответы и отклики.
Традиционно естественный путь построения клиента и
сервера – это сначала построение сервера, а затем клиента или построения их
параллельно. Но Indy имеет возможность построить
клиент или сервер, отдельно друг от друга. В некоторых случаях, один может быть
построен без необходимости доступа к другому.
В данной главе более подробно обсуждается Протокол
получения почтового кода, который был представлен ранее в его клиенте. Сам сервер будет
обсужден позже.
Проект был разработан так, чтобы быть как можно более
простым. Сервер получения почтового кода (Zip код в Америке) позволяет клиенту запросить город и
штат, к которому относится почтовый код.
Примерные данные, которые использует сервер, относятся
к американским почтовым кодам, которые у них называются zip коды. Протокол может обрабатывать и другие коды, но
американские коды уже заложены в демо программу.
Для тех, кто находится за пределами Соединенных Штатов
Америки и не знаком с их системой, zip это почтовый код в США, который указывает регион
доставки. Zip коды цифровые и состоят из 5
цифр. Zip коды могут также содержать дополнительные четыре
цифры в формате 16412-0312. Данный тип кодов получил название Zip+4. Четыре дополнительные цифры уточняют локальную
зону доставки и не требуются для определения города.
При создании протокола были приняты следующие решения:
·
Все команды
текстовые
·
Транспорт TCP
·
Порты: 6000. Порт
6000 это наиболее часто используемый номер в тестовых примерах Indy. Это не имеет значения.
Протокол поддерживает
следующие команды
·
Help – получение
справки
·
Lookup
<почтовый код 1> < почтовый код 2> ... – запрос информации
·
Quit –
отсоединение от сервера
При разработке протокола, полезно знать ключевые
протоколы, такие как - NNTP, SMTP и HTTP и
использовать их как модель. Исключая POP3 и IMAP4. Поскольку это плохой пример построения протоколов.
Команда Help очень часто
используемая команда и редко применяемая в автоматических клиентах. Данная
команда наиболее пригодна для использования человеком, который или тестирует,
или напрямую работает с сервером. Почти все серверы реализуют данную команду.
Команда Help полезна для
вывода справки о командах сервера и их возможном применении.
Для нашего протокола, сервер отвечает кодом 100, плюс
сопроводительный текст.
Команда lookup принимает
один или несколько почтовых кодов для поиска и возвращает название города и
штат. Данные возвращаются в формате RFC
откликов. Если код не найден, то отклик не возвращается (но если судить по
примеру это не так, возвращает пустой отклик – строка с точкой).
Код ответа "200 Ok".
Пример:
lookup
37642 16412
200 Ok
37642:
16412:
.
Даже если код не найден, то возвращается ответ
"200 Ok".
lookup 99999
200 Ok
.
Мы приняли такое решение. Если бы сервер мог
воспринимать только один параметр, то можно бы было отвечать кодом 200, и если
не найден, то кодом 4XX. Но протокол
может возвращать часть для правильных данных, поэтому было решено всегда
возвращать код 200.
При частично правильных данных и ответ:
lookup
37642 99999
200 Ok
37642:
.
Если бы протокол возвращал код ошибки, то частичные
данные были бы проигнорированы. Данное решение позволило серверу отвечать и на
частично правильные запросы, без генерации ошибки.
Команда quit является
прямым приказом серверу прекратить сессию и отсоединиться.
Почтовый протокол выдает многострочные ответы. Это не
определено самим протоколом. Любые RFC
ответы могут быть как однострочными, так и многострочными. Indy обрабатывает оба типа ответов автоматически.