Глубины Indy

         

Программа TraceRoute


TCP/IP пакеты не двигаются напрямую от узла к узлу. Пакеты маршрутизируются подобно движению автомобилей от одного дома до другого. Обычно, автомобиль должен двигаться более чем по одной дороге, пока не достигнет точки назначения. TCP/IP пакеты двигаются подобным образом. Каждый раз пакет сменяет «дорогу» от маршрутизатора (node) к маршрутизатору. Получив список маршрутизаторов можно определить список узлов (host), по которым путешествует пакет. Это очень полезно для диагностики, почему тот или другой узел недоступен.

Traceroute работает из командной строки, Traceroute показывает список IP маршрутизаторов, через которые проходит трасса до узла назначения и сколько требуется времени на каждый прыжок, до каждого узла. Данное время пригодна для поиска узких мест. Traceroute показывает последний маршрутизатор, который нормально обработал пакет, в случае неудачной передачи. Traceroute используется для дальнейшей диагностики после пинга.

Пример вывода работы Traceroute при удачном прохождении:

C:\>tracert www.atozedsoftware.com

Tracing route to www.atozedsoftware.com [213.239.44.103]

over a maximum of 30 hops:

1 <1 ms <1 ms <1 ms server.mshome.NET [192.168.0.1]

2 54 ms 54 ms 50 ms 102.111.0.13

3 54 ms 51 ms 53 ms 192.168.0.9

4 55 ms 54 ms 54 ms 192.168.5.2

5 55 ms 232 ms 53 ms 195.14.128.42

6 56 ms 55 ms 54 ms cosmos-e.cytanet.NET [195.14.157.1]

7 239 ms 237 ms 237 ms ds3-6-0-cr02.nyc01.pccwbtn.NET [63.218.9.1]

8 304 ms 304 ms 303 ms ge-4-2-cr02.ldn01.pccwbtn.NET [63.218.12.66]

9 304 ms 307 ms 307 ms linx.uk2net.com [195.66.224.19]

10 309 ms 302 ms 306 ms gw12k-hex.uk2net.com [213.239.57.1]

11 307 ms 306 ms 305 ms pop3 [213.239.44.103]

Trace complete.



Прокси (proxy – заместитель, уполномоченный)


Один из частых вопросов "Как я могу использовать Indy с прокси?". Когда задают этот вопрос, то ответить непросто. Не всегда возможно ответить, поскольку существует множество, самых различных прокси. Некоторые протоколы, также имеют свои собственные методы общения с прокси. Рассмотрим наиболее распространенные виды прокси.

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

Прокси могут быть разделены на две категории:

Прозрачные Непрозрачные

Простое решение


Исключение EIdConnClosedGracefully это базовый класс исключения, особенно для некоторых серверов, оно унаследовано от EIdSilentException. На закладке Language Exceptions tab of Debugger Options (Tools Menu) вы может добавить исключение EIdSilentException в список игнорируемых исключении. После этого добавленное исключение, если оно случится в коде будет обработано в программе, но отладчик не будет прерывать программу для обработки в среде.



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


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

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



Пространство имен (Namespaces)


Во избежание конфликтов и также как часть CLS (Common Language Specification), Delphi теперь поддерживает пространство имен. Каждый модуль теперь существует внутри пространства имен.

Когда вы видите объявление подобное следующему:

uses

  Borland.Delphi.SysUtils;

var

  GStatus: System.Label;

Важно заметить, что VCL for .NET находится в пространстве имен и влияет на директиву uses.



Протокол


Слово протокол происходит от греческого слова protocollon. Это страница, которая приклеивалась к манускрипту, описывающая его содержимое.

В терминах TCP/IP, протокол это описание как производить некоторые действия. НО в большинстве случаев это обычно одна из двух вещей:

1. Тип сокета.

2.      Протокол более высокого командного уровня.

Когда говорим о сокетах, то протокол описывает его тип. Распространенные типы сокетов следующие - TCP, UDP и ICMP

Когда говорим о протоколах более высокого уровня, то это относится к командам и ответам, для реализации требуемых функций. Эти протоколы описаны в RFC. Примеры таких протоколов – это HTTP, FTP и SMTP.



Протокол ICMP


ICMP это сокращение от Internet Control Message Protocol.

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



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


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

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

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

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

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

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

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

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

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

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



Протокол TCP


TCP это сокращение от Transmission Control Protocol.

Иногда TCP также называют потоковым протоколом. TCP/IP включает много протоколов и множество путей для коммуникации. Наиболее часто используемые транспорты это TCP и UDP. TCP это протокол, основанный на соединении, вы должны соединиться с сервером, прежде чем сможете передавать данные. TCP также гарантирует доставку и точность передачи данных. TCP также гарантирует, что данные будут приняты в том же порядке, как и переданы. Большинство вещей, которые используют TCP/IP - используют TCP как транспорт.

TCP соединения, подобны телефонному звонку для разговора.



Протокол UDP


UDP это сокращение от User Datagram Protocol.

UDP предназначен для датаграмм, и он не требует соединения. UDP позволяет посылать облегченные пакеты на узел без установки соединения. Для UDP пакетов не гарантируется доставка и последовательность доставки. При передаче UDP пакетов, они отсылаются в блоке. Поэтому вы не должны превышать максимальный размер пакета, указанный в вашем TCP/IP стеке.

Поэтому многие люди считают UDP малоприменим. Но это не так, многие потоковые протоколы, такие как RealAudio, используют UDP.

Примечание: термин потоковый (streaming) может быть перепутан с термином потоковое соединение (stream connection), которое относится к TCP. Когда вы видите эти термины, вы должны определить, что именно имеется в виду.

Надежность/достоверность UDP пакетов зависит надежности и перегрузки сети. UDP пакеты часто используются в локальных сетях (LAN), поскольку локальная сеть очень надежная и не перегруженная. UDP пакеты, проходящие через Интернет так же обычно надежны и могут использовать коррекцию ошибок передачи или интерполяцию. Доставка не может быть гарантирована в любой сети – потом не будем считать, что ваши данные всегда достигнут точки назначения.

Поскольку UDP не имеет средств подтверждения доставки, то вообще нет гарантии этой доставки. Если вы посылаете UDP пакет на другой узел, то вы не имеете возможности узнать, доставлен пакет или нет. Стек не может определить это и не выдает никакой информации об ошибке, если пакет не доставлен. Если вам требуется подобная гарантия, то вы должны сами организовать ответ от удаленного узла.

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

Дополнительная информация по UDP находится в главе 7.  



Протоколы SSL


Indy 10 теперь поддерживает неявный TLS и явный TLS в следующих клиентах и серверах:

POP3 SMTP FTP NNTP

Поддержка SASL кода была переработана, так что может быть использована с POP3 и IMAP4. Indy 10 теперь поддерживает анонимный SASL, плоский SASL, OTP (one-time-only password system) SASL, внешний SASL и Auth Login.



Проверка почтового индекса - протокол


Протокол клиента очень прост, он содержит только две команды:

Lookup <почтовый код 1> < почтовый код 2> ... Quit

Общение с сервером выглядит так:

Server: 204 Post Code Server Ready.

Client: lookup 16412

Server: 200 Ok

Server: 16412: EDINBORO, PA

Server: .

Client: lookup 37642 77056

Server: 200 Ok

Server: 37642: CHURCH HILL, TN

Server: 77056: HOUSTON, TX

Server: .

Client: quit

Server: 201-Paka!

Server: 201 4 requests processed.

The server responds with a greeting when the client connects. Greetings and replies to commands typically contain a 3 digit number specifying status. This will be covered more in detail in later sections.

После приветственного сообщения сервер готов принимать запросы от клиента. Если принята команда Lookup – сервер отвечает списком почтовых кодов и далее соответствующим именем города и штата. Ответ заканчивается строкой с единственным символом <точка>. Клиент может посылать множество команд, пока не выдаст команду Quit, после происходит рассоединение.



Прозрачные прокси


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

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



Пул потоков (Thread Pooling)


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

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

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

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



Путь Indy


Indy разработан изначально на использование потоков. Построение серверов и клиентов в Indy подобно построению серверов и клиентов в Unix, исключая, что это много проще, поскольку у вас есть Indy и Delphi. Приложения в Unix обычно вызывают стек напрямую с минимальным уровнем абстракции или вообще без него.

Обычно сервера в Unix имеют один или несколько слушающих процессов, которые наблюдают за пользовательскими запросами. Для каждого клиента, которого требуется обслужить, создается разветвление (fork) процесса. Это делает программирование очень простым, так как каждый процесс обслуживает только одного клиента. Процесс так запускается в собственном контексте безопасности, который может быть установлен на основе слушателя, правах, аутентификации или других предпосылках.

Сервера Indy работают подобным образом. Windows в отличии от Unix, не делает разветвление, а создает новый поток. Сервера Indy создают новый поток для каждого клиентского соединения. Сервера Indy создают слушающий поток, который изолирован от главного кодового потока программы. Слушающий поток случает входящие клиентские запросы. Для каждого клиента, которому отвечают, создается новый поток для его обслуживания. Необходимые события возбуждаются в контексте данного потока.



Рабочие очереди


Рабочие очереди организованы по принципу первый на входе - первый на выходе (FIFO),  и хранят операции (work items), запрошенные волокнами. (Work Items скорее всего абстракция для операции ввода-вывода, так как именно они блокируются) Большинство данной функциональности полностью прозрачно для среднего разработчика, так как скрыто внутри Indy.



Работа транзакций


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

Транзакции определены в Indy различными, предопределенными методами, такими как TIdHTTP.Get, WriteStream и так далее. Как пользователь, вы также можете определить свои собственные транзакции, с помощью BeginWork, DoWork и EndWork.



Разбор списка файлов FTP


Indy 10 содержит плагин для разбора списка файлов, который интерпретаторы почти для любых FTP серверов и даже возможно уже не функционирующих.

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

Поддержанные FTP сервера:

Bull GCOS 7 или Bull DPS 7000 Bull GCOS 8 или Bull DPS 9000/TA200 Cisco IOS Distinct FTP Server EPLF (Easily Parsed List Format) HellSoft FTP Server for Novell Netware 3 and 4 HP 3000 or MPE/iX, включая HP 3000 с Posix IBM AS/400, OS/400 IBM MVS, OS/390, z/OS IBM OS/2 IBM VM, z/VM IBM VSE KA9Q or NOS Microware OS-9 Music (Multi-User System for Interactive Computing) NCSA FTP Server for MS-DOS (CUTCP) Novell Netware Novell Netware Print Services for UNIX TOPS20 UniTree VMS or VMS (including Multinet, MadGoat, UCX) Wind River VxWorks WinQVT/Net 3.98.15 Xecom MicroRTOS

Примечание от переводчика: они льстят себе, на самом деле список форматов примерно раз в восемь шире.



Разделение файла .pem


Если вы посмотрите созданный .pem файл с помощью блокнота, то вы увидите, что он разделен на две части. Эти две части содержат приватный и публичный ключи. Также приведено некоторое количество информации. Indy требует, что бы данная информация была помещена в отдельные файлы.



Разделение пакетов


Indy 10 разделена на два пакета: ядро и протоколы.

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

Пакет протоколов использует ядро и реализует протоколы верхнего уровня, такие как POP3, SMTP и HTTP.

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



Различия Indy


Indy использует API блокирующих сокетов. Indy не ориентирован на события. Indy имеет события, но для информационных нужд, но они не обязательны. Indy разработан ни использование кодовых потоков. Тем не менее, Indy может работать без использования потоков. Программирование в Indy – это линейное программирование. Indy имеет высокий уровень абстрагирования. Большинство сокет компонент не очень эффективно изолируют программиста от стека. Большинство сокет компонент вместо изоляции от стека, наоборот погружают его в сложности создания оберток вокруг этого в Delphi / C++ Builder.


Размеры пакетов


Большинство операционных систем позволяют иметь размер UDP пакета 32K или даже 64K. Но, как правило, маршрутизаторы имеют более серьезные ограничения. UDP не должны превышать допустимый размер, разрешенный маршрутизатором или другим сетевым устройством. Но нет никакой возможности узнать это ограничение.

Поэтому рекомендуется, чтобы UDP пакеты были длиной в 8192 байт или менее, при передаче за пределами локальной сети.  Но в некоторых случаях и этот размер велик. Для абсолютной гарантии делайте ваши пакеты в 1024 байт или менее.



Разрешение с различиями в классах


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



Разрешение споров (Resolving Contention)


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

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

Общи пути разрешения споров приведены ниже.



Разрушение (Destruction)


Разрушение в Delphi .NET немного отличается. Большинство кода не потребует подстройки, но важно понять в чем же различие.



Реализация


Класс TCPServer содержит свойство, именуемое CommandHandlers, которое является коллекцией обработчиков команд. Обработчики обычно создаются во время разработки, тем не менее, при реализации наследников они могут создаваться и во время исполнения. Если командные обработчики создаются во время исполнения, то они должны быть созданы путем перекрытия метода InitializeCommandHandlers. Это гарантирует, что они создадутся только во время исполнения. Если они создаются в конструкторе, они будут создаваться каждый раз, когда TCPServer загружается из потока и записывается обратно в поток. Это может привести к созданию множества копий для каждого обработчика. Инициализация, напротив, вызывается только однажды после первой активации TCPServer.

Класс TCPServer содержит несколько свойств и событий имеющих отношение к обработчикам команд. Свойство CommandHandlersEnabled разрешает или запрещает работу обработчика как единого целого. Свойство OnAfterCommandHandler возбуждается после выполнения каждого  обработчика и событие OnBeforeCommand возбуждается перед выполнением каждого  обработчика. Событие OnNoCommandHandler возбуждается если обработчик, соответствующий команде, не найден.

Если свойство CommandHandlersEnabled равно true и определены обработчики, то выполняется  их обработка. Иначе вызывается событие OnExecute, если оно назначено. Обработчик OnExecute не вызывается если были обработаны команды.

Если есть соединение, TCPServer читает строки текста из соединения и пытается найти подходящий обработчик команд. Любые пустые строки игнорируются. Для непустых строк сначала возбуждается событие OnBeforeCommandHandler. Затем ищется подходящий командный обработчик. Если командный обработчик найден и его свойство enabled установлено в true, то возбуждается его событие OnCommand, а иначе возбуждается событие OnNoCommandHandler. После всего этого возбуждается событие OnAfterCommand.



Реализация DATETIME


Команда DATETIME – это последняя команда данного протокола. Оно отличатся и от QUIT и от HELP, в том, что требует особой функциональности, которая не может быть создана только с помощью свойств. Для реализации команды DATETIME будет использован обработчик события.

Для начала построим базовый обработчик команды, используя шаги с которым вы уже знакомы:

1. Создадим новый командный обработчик.

2.      Command = DateTime

3.      Name = cmdhDateTime

4.      ReplyNormal.NumericCode = 200

В данный момент свойство ReplyNormal.Text не определяется, обработчик события будет его определять для каждого ответа. Для определения обработчика, используйте инспектор объектов, выбрав командный обработчик для DATETIME. Переключитесь на закладку events и создайте событие OnCommand. Delphi создаст обработчик следующим образом:

procedure TForm1.IdTCPServer1TIdCommandHandler2Command(ASender: TIdCommand);

begin

end;

В обработчик OnCommand передается аргумент of ASender типа TIdCommand. Это не командный обработчик, а сама команда. Командные обработчики глобальны для всех соединений, тогда как, команды специфичны для соединения connection и обрабатываются в рамках экземпляра события OnCommand. Это гарантирует, что обработчик выполнит корректную обработку для каждого клиентского соединения.

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

Данный протокол определяет команду DATETIME, как имеющую дополнительный параметр, указывающий формат даты и времени. Команда (TIdCommand) реализует это с помощью свойства Params, которое является списком строк. Когда команда принимается от клиента и свойство ParseParams установлено в true (по умолчанию) Indy использует свойство CmdDelimeter (по умолчанию равное #32 или пробел) для разделения команды и параметров.

Например, в данном протоколе, клиент может послать следующее:

DATETIME hhnnss

В этом случае, свойство ASender.Params будет содержать строку "hhnnss" в свойстве ASender.Params[0]. Количество параметров может быть определено с помощью свойства  ASender.Params.Count.

Используя данные свойства обработчик OnCommand может быть реализован следующим образом:

procedure TForm1.IdTCPServer1TIdCommandHandler2Command(ASender: TIdCommand);

var

  LFormat: string;

begin

  if ASender.Params.Count = 0 then

  begin

    LFormat := 'yyyy-mm-dd hh:nn:ss';

  end

  else

  begin

    LFormat := ASender.Params[0];

  end;

  ASender.Reply.Text.Text := FormatDateTime(LFormat, Now);

end;

данная реализация просто читает параметры и использует ASender.Reply.Text для посылки ответа обратно клиенту. Не требуется устанавливать ASender.Reply.NumericCode, так как Indy инициализирует его значением 200, из командного обработчика ReplyNormal.NumericCode.

Примечание: используйте свойство ASender.Reply.Text.Text. Указание слова Text дважды требуется потому что свойство Text команды это список строк и мы имеем также TStrings.Text в дополнение к этому. Поскольку это список строк, другие методы или свойства, такие как Add, Delete и другие также могут использоваться. Свойство Text используется как ASender.Reply.Text, в некоторых случаях может быть предварительно проинициализировано и запись в него вызовет перекрытия текста.

Если снова протестировать пример с помощью telnet, то теперь ответ будет таким:

200 Hello

datetime

200 2002-08-26 18:48:06

В некоторых случаях свойство Params не может быть использовано. Свойство DATETIME одно из них. Представим себе следующую команду:

DATETIME mm dd yy

В данном случае значение свойства Params.Count будет равно 3 и событие будет неверно обработано, возвратит только значение месяца (mm). Для данных случаев, когда значение параметра включает разделители, можно использовать свойство UnparsedParams. Дополнительно, свойство ParseParams можно установить в False.

Свойство UnparsedParams содержит данные независимо от свойства ParseParams, но установка ParseParams в false увеличивает эффективность, сообщая Indy, что не требуется разбирать параметры в свойство Params.

Обработчик события, модифицированный для использования с UnparsedParams:

procedure TForm1.IdTCPServer1TIdCommandHandler2Command(ASender: TIdCommand);

var

  LFormat: string;

begin

  if ASender.Params.Count = 0 then

  begin

    LFormat := 'yyyy-mm-dd hh:nn:ss';

  end

  else

  begin

    LFormat := ASender.UnparsedParams;

  end;

     ASender.Reply.Text.Text := FormatDateTime(LFormat, Now);

end;



Реализация HELP


Команда HELP подобно по поведению на команду QUIT за исключением двух различий.

1.      Не происходит разъединение сеанса.

2.      В дополнение ответ также предоставляет текстовый отклик со справочной информацией.

Для реализации команды HELP выполним следующие шаги:

1.      Создадим новый командный обработчик.

2.      Command = Help

3.      Name = cmdhHelp

4.      ReplyNormal.NumericCode = 200

5.      ReplyNormal.Text = Help Follows

Все эти шаги знакомы вам по реализации команды QUIT. Дополнительное свойство, которое здесь используется - это свойство Response, которое является списком строк. Если свойство Response содержит текст, то оно посылается клиенту после отсылки ReplyNormal. Для реализации команды HELP используется редактор строк свойства Response:

Help - Display a list of supported commands and basic help on each.

DateTime <format> - Return the current date and/or time using the specified

format.

If no format is specified the format yyyy-mm-dd hh:nn:ss will be used.

Quit - Terminate the session and disconnect.

Теперь если вы подсоединитесь к серверу и пошлете команду HELP, то сервер ответит следующим образом:

200 Hello

help

200 Help Follows

Help - Display a list of supported commands and basic help on each.

DateTime <format> - Return the current date and/or time using the specified

format.

If no format is specified the format yyyy-mm-dd hh:nn:ss will be used.

Quit - Terminate the session and disconnect.

.



Реализация критических секций


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

Часто одна критическая секция используется для защиты множества ресурсов. Допустим, что ресурсы A, B и C имеют одну общую критическую секцию для их защиты, хотя каждый ресурс независим. Проблема возникает, когда используется B, то A и C также заблокированы. Критические секции простые и выделенная критическая секция должна использоваться для каждого ресурса.

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



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


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

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

1.      Стандартный – эти протоколы относятся к Интернет стандартам. Для понимания просто найдите в RFC нужный протокол. В RFC  протокол рассмотрен в подробностях.

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

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

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

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

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

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

1xx - информационные 2xx - успешные 3xx – временные ошибки 4xx – постоянные ошибки 5xx – внутренние ошибки

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



Реальные ограничения на потоки


Реально средняя система начинает испытать проблемы, только когда процесс создаст свыше 1000 потоков, из-за нехватки памяти. Размер стека потока может быть уменьшен за счет увеличения количества потоков, тем не менее, надо рассмотреть и другие альтернативные причины.

Большинству серверов требуется только несколько сотен потоков. Тем не менее, сильно нагруженные сервера или сервера, у которых трафик низкий, но множество подключенных клиентов, таких как чат (Chat) сервер требуют другой реализации. Такие сервера, в Indy могут создавать тысячи потоков.

Также следует понять, что количество клиентов совсем не означает тоже количество конкурирующих потоков. Когда каждый клиент выделяет отдельный поток, то поток выделяется клиенту только при соединении. Многие сервера обслуживают кратко живущие соединения, такие как HTTP сервера. HTTP соединения для страниц обычно живут только одну секунду или менее, особенно если используется прокси или кэширование. Предположим 1 секунду на соединение и только 500 потоков, что позволяет до 30 000 клиентов в час.

Indy 10 имеет и другие модели, в дополнение к потокам серверов. Возможности Indy 10 ограничены только размером доступной памяти для размещения сокетов.



RFC


RFC это сокращение от Request for Comments.

RFC это набор официальных документов от IETF, которые описывают и детализируют протоколы Интернет. Документы RFC идентифицируются их номера, подобными RFC 822.

Есть очень много зеркал, которые содержат документы RFC в Интернет. Лучший из них, который имеет поисковую системе находится на сайте http://www.rfc-editor.org/

RFC редактор (web сайт указанный выше) описывает документы RFC как:

Серия документов RFC – это набор технических и организационных заметок об Интернет (изначально ARPANET), начиная с 1969 года. Заметки в серии RFC документов дискутируют многие аспекты компьютерных сетей, включая протоколы, процедуры, программы и концепции, как заметки, мнения, а иногда и юмор.



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 – внутренние ошибки

Числа обычно уникальные, но не всегда. Если вы назначите 201 для "File not found", многие команды могут отвечать этим кодом и значение всегда одно. В некоторых редких случаях, значение числа зависит от примененной команды. В этом случае, каждая команда назначает специфическое значение each command assigns specific meanings to each numeric reply.

Цифровые коды, заканчивающие на 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!



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


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

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

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

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



RFC – отклик (response)


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

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

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



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


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

Примет транзакции:

GET File.txt

201 File follows

Hello,

Thank you for your request, however we cannot grant your

request for funds for researching as you put it in your

application "A better mouse trap".

Thank you, and please do not give up.

.



Роль потоков


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

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

Сервера Indy работают подобным образом. Windows в отличии от Unix не размножает процессы, но зато Windows хорошо работает с потоками. Сервера Indy размещают поток для каждого клиентского соединения, вместо создания отдельного законченного процесса, как это делает Unix. Это дает все преимущества процессов, без наличия недостатков.



Сборка (Assembly)


Сборка это коллекция .NET IL модулей. Это очень похоже на пакеты в Delphi и Delphi .NET трактует .NET сборки аналогично пакетам Delphi.



Сборка мусора (Garbage Collection)


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

Сборка мусора .NET очень сложная и даже базовая информация заслуживает отдельной главы, если даже не статьи.

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



Сценарий записи в файл


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

1. Открыть файл

2.      Записать данные

3.      Закрыть файл



Семафоры (Semaphores)


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

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

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



Сервер


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

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



Сервер FTP


FTP теперь поддерживает:

Команды MFMT и MFF. (http://www.trevezel.com/downloads/draft-somers-ftp-mfxx-00.html) Команды XCRC и COMB для поддержки режима многоблочной передачи файлов Cute FTP Pro. Поддержаны команды для MD5 и MMD5 (http://ietfreport.isoc.org/ids/draft-twine-ftpmd5-00.txt) Поддержаны некоторые ключи Unix, которые относятся к перечислению директорий,  это включает ключ (-R) для получения рекурсивного списка. Поддержан формат Easily Parsed List файлов на сервере. (http://cr.yp.to/ftp/list/eplf.html). Добавлен OTP калькулятор, который может использоваться на FTP сервере. Компонент виртуальной системы может теперь быть использован для более легкого построения FTP сервера. Добавлены специфические для FTP расширения IP6.

Добавлена возможность запрещения команды FTPX. Это сделано для предотвращения нарушений защиты с использованием команд Port и PASV, причины описаны здесь:

http://www.cert.org/tech_tips/ftp_port_attacks.html http://www.kb.cert.org/vuls/id/2558 http://www.cert.org/advisories/CA-1997-27.html http://www.geocities.com/SiliconValley/1947/Ftpbounc.htm http://cr.yp.to/ftp/security.html

Сервер SSL


Реализация SSL сервера немного более сложная, чем реализация SSL клиента. С клиентами, все что требуется это сделать хук TIdTCPClient или его наследникам к экземпляру TIdSSLIOHandlerSocket. Это происходит потому что, поскольку сервер выполняет больше работы для поддержки SSL.

Для реализации SSL сервера используется TIdServerIOHandlerSSL. TIdTCPServer's имеет свойства для установки хука на TIdServerIOHandlerSSL. Но в отличие от TIdSSLIOHandlerSocket (Client), класс TIdServerIOHandlerSSL требует несколько дополнительных шагов. Более конкретно - должен быть установлены сертификаты. Данные сертификаты должны быть представлены как файлы на диске и указаны в CertFile, KeyFile и RootCertFile, в соответствующих свойствах SSLOptions.

Сертификаты обычно получают из уполномоченных источников. Вы можете иметь свой собственный сертификат и своего собственно источника, но ни один из браузеров не будет доверять вашим сертификатам и браузер будет выдавать диалог с предупреждением при соединении с вашим сервером. Если вы желаете распространять через Интернет, то вы должны получить сертификат из корневого хранилища, которому стандартный браузер будет доверять. Единственный сертификат, которому доверяют все браузеры – это сертификат от Verisign. Можно также использовать сертификат от Thawte, но не все браузеры доверяют ему по умолчанию. Примечание от переводчика: самое смешное, что Thawte принадлежит Verisign

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

Примечание: это относится только к HTTP серверам, но SSL не ограничен использованием только в HTTP. Вы можете реализовать SSL и получить полный контроль над правилами получения и принятия сертификатов.



Серверы


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



Сервис DNS


DNS это сокращение от Domain Name Service.

Задача DNS преобразовывать имена узлов в IP адреса. Для установки соединения, требуется IP адрес, DNS используется, чтобы сначала преобразовать имя в IP адрес.

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



Сетевой порядок байт


Различные компьютерные системы хранят числовые данные в различном порядке. Некоторые компьютеры хранят числа, начиная с самого наименее значимого байта (LSB), тогда как другие с наиболее значимого байта (MSB). В случае сети, не всегда известно, какой компьютер используется на другой стороне. Для решения этой проблемы был принят стандартный порядок байт для записи и передачи по сети, названый сетевой порядок байт. Сетевой порядок байт это фиксированный порядок байт, который должен использоваться в приложении при передаче двоичных чисел.



Сетевые интерфейсы


Indy 9 имела только один сетевой интерфейс. В Windows этот интерфейс был Winsock и на Linux стек. Indy 10 еще продолжает поддерживать этот интерфейс, но имеет также и более эффективные интерфейсы в Windows. В данное время никаких других интерфейсов в Linux не реализовано, но возможно они появятся в будущем. Это не так важно в Linux, поскольку у него своя сетевая семантика.

Некоторые из дополнительных интерфейсов не доступны во всех версиях Windows и должны использоваться только в серверных реализациях или в системах с высоким количеством клиентских соединений. Клиенты не нуждаются в этих продвинутых возможностях.

Дополнительные интерфейсы следующие:

Перекрытый ввод/вывод (Overlapped I/O) Порты завершения ввода/вывода (I/O Completion Ports)

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



Шаги по переносу


Перенос приложений в Delphi .NET для большинства приложений будет очень значимым и потребует определенной осторожности. Для большинства объектно-ориентированного кода, проще чем кажется. Данная статья не может уменьшить количество работы по переносу, но поможет вам сделать это легче. Она позволит уменьшить количество ошибок и предназначена для быстрой реализации переноса.



Схема с подтверждениями


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

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



Схема с последовательностями


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

Такое поведение при потерянных пакетов можно услышать при передачи реальной речи при передачи по сотовому телефону. В некоторых случаях вы слышите пропуски или заикания.



Широкополосносные сообщения (Broadcast)


UDP имеет уникальную возможность, что его делает очень применимым. Это возможность широкополосной посылки. Широкополосность (Broadcast) означает, что может быть послано одно сообщение, по получено многими получателями. Это не то же самое, как многоадресность (multicasting). Многоадресность – это модель подписки. Когда получатели делают подписку на получение и они добавляются в список рассылки. С помощью широкополосной рассылки, сообщение посылается по сети и все кто его слушают, могут принять его, без необходимости подписываться.

Многоадресные сообщения подобны газетной рассылки. Только те люди, которые подписались на доставку, получают его. Широкополосные сообщения аналогичны радиовещанию (От переводчика: в английском языке это одно и тоже слово broadcasting). Любой, кто имеет радиоприемник, может настроить его на любую радиостанцию и принимать ее. Радиослушатель не обязан оповещать радиостанцию, что он хочет слушать.

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

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



Show Any Key


Данный параметр, может быть использован для дополнительных выходок. BSOD выдает подсказку «нажмите любую клавишу для продолжения». Это так в нормальном BSOD. НО в данном случае, если будет отмечен, то после нажатия любой клавиши, будет выдано другое сообщение с мигающим текстом «Это не та клавиша, нажмите клавишу NY!».

Этот параметр должен отвратить вашего босса или Бейсик программиста потратить часы на поиск клавиши. Данный параметр наиболее хорошо использовать до отправки в аэропорт для длительного путешествия или когда вы хотите занять его надолго. (А себя в длительных поисках новой работы)



Show Trademark


Если данный параметр используется, то в нижнем углу экрана будет мелкая, но читаемая  надпись: * The BSOD is a trademark of the Microsoft Corporation.