Глубины Indy

         

Симуляция


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

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

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



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


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



Синхронизация


Синхронизация – это процесс передачи информации из вторичного потока основному. VCL поддерживает это с помощью метода Sychronize класса TThread.



Синхронизация (Synchronizations)


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

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

Используйте оповещение везде где только возможно.



Скажем прощай


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

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

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

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



Событие OnExecute


Событие OnExecute ссылается на событие OnExecute класса TIdTCPServer. При реализации сервера по данной модели, должно быть определено событие OnExecute или перекрыт метод DoExecute.

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

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

1. Помнить о том,  что событие возникает в цикле.

2.      Не препядствовать Indy выполянть обработку в цикле.

Внутренний цикл показан на следующей диаграмме:

На этапе проверки соединения выполняется следующие проверки:

Клиент еще подсоединен Disconnect не был вызван во время OnExecute Отсутствуют фатальные ошибки Не было возбуждено необработанное исключение в OnExecute Сервер еще активен

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



События (Events)


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



События OnWork


События OnWork состоят из трех событий и используется для связи состояний транзакций. Эти три события следующие: OnWorkBegin, OnWork и OnWorkEnd.

При начале транзакции возникает событие OnWorkBegin. В событие OnWorkBegin передаются Sender, WorkMode и WorkCount. Параметр Sender это соединение, к которому относится транзакция. Параметр WorkMode указывает режим работы – читающая или пишущая транзакция. Транзакции Read и Write могут возникать одновременно и транзакции могут быть вложенными. Параметр WorkCount указывает размер транзакции. Во многих транзакциях, размер не может быть определен, и в этом случае, WorkCount имеет значение 0. Иначе, WorkCount показывает количество байт. Обычно данное событие используется для отображения начала процесса.

Затем возникает серия событий OnWork. В событие OnWork передаются Sender, WorkMode и текущий WorkCount. Данное событие используется для отображения прогресса.

Когда транзакция заканчивает, возникает событие OnWorkEnd. В событие OnWorkEnd OnWork передаются только Sender и WorkMode. Данное событие используется для отображения завергения процесса.



События потоков


События TIdTCPServer потоковые. Это означает, что они не являются частью потока, они выполняются внутри потока. Это очень важная деталь. Будьте уверены, что вы понимаете эту деталь до начала обработки.

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

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

Каждый клиент создает свой собственный поток. При использовании данного потока, события TCP сервера (который является частью формы или модуля данных) вызываются из данных потоков. Это означает, что одиночное событие может быть вызвано множество раз из разных потоков. Такие события получают в качестве аргумента AThread, который указывает на поток из которого возбуждено событие.

Примерами потоковых события являются командные обработчики сервера OnConnect, OnExecute и OnDisconnect.



SOCKS прокси


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

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

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

Поскольку SOCKS протокол работает динамически на основе переданных данных, он очень настраиваемый и гибкий.



Сокет


Все что здесь говорится об сокетах, относится к TCP/IP. Сокет это комбинация IP адреса, порта и протокола. Сокет также виртуальный коммуникационный трубопровод между двумя процессами. Эти процессы могут быть локальными (расположенными на одном и том же компьютере) или удаленными.

Сокет подобен телефонному соединению, которое обеспечивает разговор. Для того чтобы осуществить разговор, вы обязаны в первую очередь сделать вызов, получить ответ с другой стороны; другими словами нет соединения (сокета) - нет разговора.



Сотни потоков


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

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

Моя система имеет 513 созданных потоков:

Вы видите, что даже при 513 потоках процессор нагружен только на 1%. Сильно нагруженный сервер IIS (Microsoft Internet Information Server) может создать сотни и тысячи потоков. Данный тест был выполнен на Pentium III 750 MHz с 256 MB оперативной памяти.

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

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



Создание обработчика команд


Обработчики команд создаются при редактировании свойства CommandHandlers класса TIdTCPServer. Свойство CommandHandlers – это коллекция. Обработчики могут быть модифицированы как во время исполнения, так и во время разработки. Для редактирования  обработчиков во время разработки нажмите на кнопку <…> на свойстве CommandHandlers в инспекторе объектов. Появится следующий диалог:

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

Для редактирования обработчика выберите его в инспекторе объектов. Редактирование  обработчиков подобно редактированию полей набора данных БД или колонок в DBGrid. Если инспектор объектов не виден, то нажмите F11 для его отображения.

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

Пошаговое описание реализации команды QUIT:

1. Command = Quit – это команда сервера которую сервер будет использовать для поиска обработчика при чтении ввода. Команда не чувствительна к регистру.

2.      Disconnect = True – это значит, что сервер отсоединится от клиента после получении и  обработки данной команды.

3.      Name = cmdhQuit – данное свойство не оказывает никакого влияния на обработку, но оно предназначено для упрощения идентификации обработчика в коде. Данный шаг необязательный.

4.      ReplyNormal.NumericCode = 200 – Команды обычно возвращают 3-х разрядный код и необязательный текст.  Задав это свойство, мы указывем обработчику возвращать в ответ на команду код 200 и дополнительный текст из ReplyNormal.Text если конечно не произойдет ошибка во время выполнения команды.

5.      ReplyNormal.Text = Good Bye – дополнительный текст, который посылается вместе с ReplyNormal.NumericCode.

После этого мы имеем полностью работоспособный обработчик команд.



Специальное примечание к классу TMREWS


До Delphi 6 в классе TMultiReadExclusiveWriteSynchronizer имелась проблема, приводящая к взаимному блокированию (dead lock) при повышении уровня блокировки с чтения на запись. Поэтому, вы не никогда должны использовать данную возможность изменения блокировки чтения в блокировку записи, несмотря на то, что документация утверждает что это можно сделать.

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

Класс TMultiReadExclusiveWriteSynchronizer так требует особой осторожности при использовании в Delphi 6. Все версии класса TMultiReadExclusiveWriteSynchronizer включая, поставляемый в update pack 1 и в update pack 2 имеют серьезные проблемы, которые могут вызвать взаимную блокировку. Обходных путей пока нет.

Borland в курсе этого и выпустил неофициальный патч и также ожидаются официальные патчи.



Сравнение производительности


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

Класс TMREWS более сложен и поэтому больше влияет на производительность. Он должен управлять списком запросов для поддержания состояния блокировок.

Для того чтобы продемонстрировать разницу был создан демонстрационный проект ConcurrencySpeed.dpr. Он проводит три простых замера:

1.      TCriticalSection – Enter и Leave

2.      TMREWS – BeginRead и EndRead

3.      TMREWS – BeginWrite и EndWrite

Он делает это выполняя цикл заданное количество раз. Для примера 100000. В моих тестах я получил следующие результаты.

TCriticalSection: 20

TMREWS (Read Lock): 150

TMREWS (Write Lock): 401

Конечно, результаты зависят от компьютера. Но важна разница, а не абсолютные числа. Я могу видеть что при оптимальных условиях запись TMREWS в 7.5 раз медленне критических секций. А запись медленнее в 20 раз.

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



Сравнение технологий


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

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

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

Забудьте все, что вы знали раньше!

Это легко сказать, труднее сделать, менять привычки тяжело. Чтобы подчеркнуть разницу, приведем абстрактный пример. Для абстрагирования концепции, используем в качестве аналога файлы. Данный документ подразумевает, что вы умеете работать с файлам. Надеемся, что Бейсик программисты не читают эту книгу.



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


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

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

3 File1 события 1 поле в Form

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



Среда .Net Framework


Среда .NET framework – это библиотека классов, которая является ядром .NET. Данная библиотека классов включает классы для ввода/вывода, хранения данных, простые типы, комплексные типы, доступ к базам, пользовательский интерфейс и многое другое. То чем VCL является для Delphi программистов, тем же является для .NET программистов.

АПИ Win32 ушло и было заменено классами в среде .NET, которое предоставляет лучшую и более абстрактную платформу с независимым интерфейсом. Так же предоставлен и прямой доступ до Win32 API, и до DLL. Тем не мене использования подобного доступа делает ваш код не обслуживаемым и нежелательным в .NET приложениях.



Среда VCL for .Net


Среда VCL for .NET относится к новому VCL, который работает под .NET и предоставляет уровень совместимости для старых приложений и добавляет дополнительную функциональность.

Среда VCL for .NET позволяет сделать более быстрый перенос существующих приложений, аналогично Win32 VCL и CLX. Это позволяет продолжать разработку кросс платформенных приложений. Это важное свойство, которое позволяет продолжать поддержку Windows приложений без .NET framework и также Linux.



Среда WinForms


Среда WinForms – это сборка в .NET framework, которая включает классы для форм, кнопки, органы редактирования и другие элементы GUI для построения GUI приложений. Среда WinForms – это .Net управляемы интерфейс к Win32 API и – это то, что Visual Studio .NET использует для построения GUI приложений.



SSL – безопасные сокеты


SSL – это сокращение от Secure Socket Layer и является проверенным методом шифрования данных передаваемых через Интернет. SSL обычно используется для HTTP (Web) трафика и называется защищенный (secured) HTTPS. Конечно, SSL не ограничен HTTP и может быть использован с любым TCP/IP протоколом.

Для использования SSL в Indy, вы во-первых должны установить поддержку SSL. Indy реализует поддержку SSL в открытом для расширения стиле, но единственная поддерживаемая сейчас реализация библиотеки SSL - это OpenSSL. Библиотека OpenSSL доступна, как набор DLL и доступна для загрузки отдельно от дистрибутива Indy.

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

Ограничение касается только на распространение в электронном виде, но не на предоставление исходного кода в печатном виде. Даное ограничение касается только экспорта и не является важным.

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

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

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



Стек протоколов


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

В Windows стек протоколов реализован с помощью Winsock.



Стек протоколов TCP/IP


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

TCP/IP может означать разные вещи. Очень часто в общем как слово «хватать все» (catch all). В большинстве других случаев, это относится к сетевому протоколу само по себе.



Свойство Greeting (приветствие)


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

Установите свойства Greeting. NumericCode = 200 и Greeting.Text в "Hello".



Свойство InputBuffer


property InputBuffer: TIdManagedBuffer read FInputBuffer;

Свойство InputBuffer – это ссылка на экземпляр объекта TIdManagedBuffer. InputBuffer – это внутренний буфер Indy. TIdManagedBuffer имеет несколько расширенных буферов, но обычно пользователь не использует их.



Свойство ReplyExceptionCode


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

Установите ReplyExceptionCode в 500.



Свойство ReplyUnknownCommand


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

Установите ReplyUnknown.NumericCode в 400 и ReplyUnknown.Text в "Unknown Command".



Таймауты чтения


TIdTCPConnection (Все TCP клиенты и соединения, которые унаследованы от TIdTCPConnection) имеет свойство, названое ReadTimeout. Свойство ReadTimeout указывает таймаут в миллисекундах. Значением свойства по умолчанию является IdTimeoutInfinite. Данная установка запрещает таймауты.

Таймаут не является таймаутом окончания работы. Это просто пустой таймаут. Что это значит, если указанная величина в свойстве ReadTimeout прошло и не данных для записи, то будет возбуждено исключение EIdReadTimeout.

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

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

Во время чтения, если в течение указанного интервала не будет приема данных из соединения, то возникнет исключение EIdReadTimeout. Таймаут не применяется если принимаются данные в течение периода. Если вы запросили 100 байт и таймаут 1000 миллисекунд (1 секунда) операция чтения может занять более одной секунды. От переводчика: если в будет в течение каждой секунды принимать по одному байту, то в результате прием займет 100 секунд.

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



Термин потоко-безопасный (threadsafe)


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

Примером потоко-безопасных классов является VCL класс TThreadList, а также потоко-безопасные классы Indy. Конечно операционная система также потоко-безопасна.



Термин потоковый (threadable)


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

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

Примеры потоковых переменных – это значения типа Integer, String и другие ординарные типы, TList, TStringList и большинство невизуальных классов.

Объект может иметь доступ к глобальным переменным или элементам управления GUI. Неограниченное (а часто и не нужное) использование глобальных переменных в большинстве  случаях, это то что мешает сделать компоненты потоковыми.

Объект может быть библиотекой, компонентом, процедурой или .



Терминология протокола


Перед обсуждением реализации протокола рассмотрим некоторые термины.



Термины


Данная статья сфокусирована на преобразовании и его последствиях для вашего Delphi кода. Поэтому, данная статья не является введением в .Net саму по себе, а только дает определение основных базовых терминов, относящихся к .NET.



Термины потоковый (threadable) и потоко-безопасный (threadsafe)


Термин потоко-безопасный (threadsafe) часто используется или трактуется неправильно. Его часто применяют  одновременно к потоковый (threadable) и потоко-безопасный (threadsafe), что   приводит к ошибкам. В данном тексте, термины потоковый и потоко-безопасный точно определены и имеют разное значение.



Тестирование новой команды


Теперь, когда команда уже реализована можно приступить и к тестированию, просто воспользуемся Telnet, поскольку протокол текстовый:

1. Запустим приложение.

2.      В меню Start: Run введем: telnet 127.0.0.1 6000 и нажмем OK. Это указывает Telnet подсоединиться к компьютеру на порт 6000, который используется в демонстрационном примере.

3.      Сервер должен ответить 200 Hello, что является приветствием, из свойства Greeting of TIdTCPServer.

4.      Telnet затем покажет каретку. Это означает, что сервер готов и ожидает команду.

5.      Введем HELP и нажмем enter. Сервер ответит "400 Unknown Command". Поскольку пока мы не создали командного обработчика для команды HELP и ответ "400 Unknown Command" был взят из свойства ReplyUnknown.

6.      Введем QUIT. Сервер ответит "200 Good Bye" и отсоединится от клиента.

Поздравляем! Вы построили сервер с обработчиком команд. В следующей главе мы реализуем остальные две команды - HELP и DATETIME, которые имеют отличное от команды QUIT поведение.



Только чтение (Read Only)


Самый простой метод – это режим только чтение. Все простые типы (integers, strings, memory), которые используются в режиме только чтения - не требуют защиты. Это также относится и к таким сложным типам как TList и другие. Классы безопасны если только не используют глобальные переменные или глобальные поля классов в режиме чтения/записи.

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



Туннелирование IP / Трансляция сетевого адреса (NAT)


IP маскирование ли трансляция сетевого адреса (NAT) в прокси позволяет всем исходящис соединеним быть прозрачными и не оказывать влияния на клиентов. Клиенты продолжают работать как обычно и не требуется их конфигурирование.

Microsoft Internet Connection Sharing работает по данному методу.



Удаление предупреждений (Unsafe Warnings)


To remove unsafe warnings, load the target project into Delphi 7. With the unsafe warnings turned on, perform a build all. Delphi will produce a series of unsafe warnings. Each warning needs to be eliminated. This may easily be the biggest step in porting your application.



Управление потоками


Управление потоками абстрагировано в Indy в менеджеры потоков. Менеджеры потоков позволяют иметь различные (даже пользовательские) реализации стратегий управления потоками.

Управление потоками - это необязательная дополнительная возможность. Если вы не определяете менеджер потоков в свойстве ThreadManager в компоненте, который поддерживает управление потоками (таком как TIdTCPServer) Indy неявно создает и уничтожает экземпляр менеджера потоков.



Управление приоритетами (Prioritization)


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

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

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

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



Управление своими собственными рабочими транзакциями


Вы можете создавать свои собственные транзакции, вызывая BeginWork, DoWork и EndWork. Параметры те же самые, что описанны выше. Вызовы вложенных транзакций обслуживаются автоматически.

Для выполнения транзакции, сначала вызовите BeginWork с указанием размера, если он известен. Затем вызовайте DoWork для отображения прогресса. По окончанию вызовите EndWork.



Управляемый код (Managed Code)


Управляемый код – это код который компилируется в IL и исполняется с помощью CLR. Основная цель любого .NET приложения – это быть 100% обслуживаемым кодом. (От корректора: Ну, блин сказал... J)



Use a Custom Message


Если данный параметр отмечен, то появляется другой диалог в котором вы можете ввести свое сообщение. Данный параметр полезен для организации интерактивных и более уместных BSOD сообщений. Например, если ваш шеф в необычной одежде, то вы можете создать такое сообщение:

Ugly brown suit error. I cannot continue in such company. (Очень неприятная ошибка в одежде. Я больше не могу оставаться далее в такой компании).



Установка


Сервер назван svchost (еще одна любимая вещь у вирусов) вместо RBSODServer или другим более говорящим именем. Это сделано, чтобы для более простой установки на другом компьютере и одновременно скрываете его. Имя svchost – это нормальное имя системного исполнимого файла, который запускает множество копий исполнимых файлов. Если вы посмотрите в диспетчере задач, то вы несколько запущенных копий подобного процесса. Поскольку вы разместите свой специальную копию в другой папке, а не в системной, то он не будет драться с родным, но будет выглядеть как нормальный в диспетчере задач.

Сервер не имеет окон и не появляется в панели задач и системном трее (там, где часики). Если вы хотите его остановить, то запустите диспетчер задач и выберите тот svchost, который запущен от имени пользователя. Системный svchosts запущен от SYSTEM (это не совсем так). После выбора вашей «версии» нажмите клавишу [Снять задачу].

Для инсталляции просто скопируйте сервер на машину клиента (compile without packages for easiest deployment) и запустит его. Он останется в памяти пока пользователь не перезагрузит свой компьютере. После перезагрузки программа не будет перезапущена. Если вы желаете, что бы программа автоматически стартовала при каждой перезагрузки, то просто добавьте ее в автозагрузку или в реестр, для невидимого запуска.



Узкие места


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

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

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

Несколько узких мест будет рассмотрено ниже.



Ведение логов


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



Ведение логов (Logging)


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

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

Специализированные классы логов, следующее:

TIdLogEvent – возбуждает события, когда данные приняты, или переданы, или при появлении события состояния. Класс TIdLogEvent полезен для реализации пользовательских логов, без необходимости в реализации нового класса. TIdLogFile – Записывает данные в файл. TIdLogDebug – Записывает данные в окно отладки Windows или в консоль Linux. Также отмечает данные, как принятые данные, переданные данные или информация о статусе. Класс TidLogDebug полезен для проведения простой отладки. TIdLogStream – Не добавляет комментариев, отметок к данным, как другие классы. Вместо этого просто записывает сырые данные в указанный поток. Класс TIdLogStream может использоваться по разному, но обычно он очень эффективно используется для QA тестирования и удаленной отладки. Могут быть построены и пользовательские классы логов.

Borland довольно молчалив по поводу


Borland довольно молчалив по поводу Delphi 8. Тем не менее, опираясь на публичные высказывания мы может сделать кое какие вывод насчет Delphi 8.  Видно, это будет не Delphi .NET, а расширение для платформы Windows. (От переводчика: это не подтвердилось.)


Вложенные типы (Nested Types)


Вложенные типы позволяют объявление типов внутри другого объявления типа.



Волокна (Fibers)


В дополнение к расширению поддержке потоков, Indy 10 содержит и поддержку волокна. Что такое волокно? Если коротко, то это "поток", который контролируется кодом, а не операционной системой. В действительности, поток может быть трактоваться, как продвинутое волокно. Волокна подобны Unix пользовательским потокам. (От корректора: Вот и до слово блудились... Поток или волокно? Что там на у них? Сейчас уже вроде есть потоки и процессы...)

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

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

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

При использовании волокон, Indy так преобразовывает сложность низкоуровневых интерфейсов в дружественные пользователю интерфейсы.

Пока волокна могут быть применены только в Windows.



Введение


Добро пожаловать в книгу «Погружение в Indy»

Авторы:

Чад Хувер (Chad Z. Hower a.k.a Kudzu) – Автор Indy и текущий координатор проекта Indy Хади Харири (Hadi Hariri) – помощник координатора проекта Indy

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



Выбор между Critical Sections и TMREWS


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

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

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

Класс TMREWS работает лучше, если встретятся следующие условия:

1. доступ осуществляется по чтению и записи.

2.      преобладает доступ по чтению.

3.      период блокировки велик и не может быть разбит на меньшие независимые куски.

4.      доступен пропатченый класс TMREWS и известно что он работает корректно.



WAN


WAN это сокращение от Wide Area Network.

WAN означает соединение нескольких LAN совместно, с помощью мостов и маршрутизаторов в одну большую сеть.

Используя пример с городом, WAN состоит из множества городов (LAN) соединенных скоростными трассами. Интернет сам по себе классифицируются как WAN.



Winsock


Indy 9.0 требует установленного Winsock 2.0, Windows 98, Windows NT и Windows 2000 имеют установленный Winsock 2.0 по умолчанию. При запуске Indy проверяет версию Winsock.

Windows 95 единственная операционная система, которая не содержит Winsock 2.0. Но его можно установить, если загрузить обновление с сайта Microsoft. Адрес для загрузки следующий: http://www.microsoft.com/windows95/downloads/contents/wuadmintools/s_wunetworkingtools/w95sockets2/

Патч требуется установить в любом случае, поскольку Winsock, который поставляется с Windows 95 имеет серьезные ошибки и утечки памяти, данный патч их устраняет. Windows 95 в данный момент уже редко распространен, менее 5% от общего количества от установленных систем. Еще меньшее количество из них подключено к Интернет, что не вызовет проблем при распространении ваших приложений.


Winsock – это сокращение от Windows Sockets.

Winsock – это определенное и документированное стандартное API, для программирования сетевых протоколов. В основном используется для программирования TCP/IP, но может быть использовано и для программирования Novell (IPX/SPX) и других сетевых протоколов. Winsock реализован как набор DLL и является частью Win32.



Заключение


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

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



Запись и воспроизведение


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

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

Обработчики ввода/вывода (IOHandlers) также имеют другое полезное применение. Они используются для записи и воспроизведения. Живая сессия может быть записана с помощью компонентов ведения логов и позже воспроизведена с помощью потоков обработчиков ввода/вывода. Представим, что вы имеет заказчика, у которого есть проблемы, но вы не можете воспроизвести эти проблемы у себя и не можете посетить его. Вы можете попросить его прислать лог полной сессии и попытаться воспроизвести сессию на вашей машине. Команда Indy использует это как часть своей QA отладки. Я планирую описать это позже.



Защита ресурсов (Resource Protection)


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