Глубины Indy

         

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


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

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

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

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

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

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

Client: lookup 37642 77056

Server: 200 Ok

Server: 37642: CHURCH HILL, TN

Server: 77056: HOUSTON, TX

Server: .

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

Команда:

Client: lookup 37642 77056

Ответ:

Server: 200 Ok

Отклик:

Server: 37642: CHURCH HILL, TN

Server: 77056: HOUSTON, TX

Server: .



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



А когда это ошибка?


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

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



А нужно ли вам реально знать это?


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

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



Атомарные операции (Atomic Operations)


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

Обычно задачи, такие как чтение или запись целых чисел (integer) или логических полей (boolean field) являются атомарными операциями, так как они выполняются с помощью единственной инструкции move. Тем не менее моя рекомендация, такая – никогда не рассчитывайте на атомарность операций, поскольку в некоторых случаях, даже при записи целого (integer) или логического (Boolean) может быть выполнено более одной инструкции, в зависимости от того, откуда данные читались. В дополнение, это требует знания внутренней природы компилятора, которое является предметом для изменения в любое время, без вашего оповещения. Закладываясь на атомарные операции вы можете написать код, который будет неоднозначным в некоторых случаях и может работать по разному на многопроцессорных машинах или других операционных системах.

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

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



Базовый клиент


Базовый клиент Indy выглядит так:

with IndyClient do

begin

  Host := 'test.atozedsoftware.com';

  Port := 6000;

  Connect;

  Try

    // Read and write data here

  finally

    Disconnect;

  end;

end;

host и port могут быть установлены во время разработки с помощью инспектора объектов. Это минимальный код, который требуется при написании клиента в Indy. Минимальные требования для создания клиентов следующие:

1. Установка свойства Host.

2.      Установка свойства Port. Требуется, если нет порта по умолчанию. Большинство протоколов имеют такой порт.

3.      Соединение.

4.      Передача данных. Включает чтение и запись.

5.      Разъединение.



Базовый пример


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

1.      Создадим новое приложение.

2.      Добавим TIdTCPServer на форму.

3.      Установим свойство TIdTCPServer.Default в 6000. порт 6000 это порт для демо, выбранный случайным образом,  можно использовать любой свободный порт.

4.      Установим свойство TIdTCPServer.Active в True. Это должно активировать сервер при старте приложения.

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



Бесплатная поддержка


Бесплатная поддержка может быть получена через группы новостей Borland.

borland.public.delphi.internet.winsock borland.public.cppbuilder.internet.socket borland.public.kylix.internet.sockets

Все группы новостей расположены на newsgroups.borland.com. Если у вас нет доступа до групп по NNTP, то вы можете читать их через web интерфейс на http://newsgroups.borland.com. Команда Indy просматривает эти группы регулярно и старается помочь.



Beta


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

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



Безопасность


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



Безопасные протоколы HTTP и HTTPS


Реализация протокола HTTPS в Indy очень проста. Просто укажите безопасный URL вместо стандартного URL и Indy клиент HTTP (TIdHTTP) все остальное сделает автоматически. Чтобы сделать URL безопасным, просто измените http:// на https://.

Примечание: чтобы HTTPS сессия была установлена, web сервер, который отвечает должен поддерживать SSL и иметь установленный сертификат шифрования. Также HTTP клиенты Indy  не проверяют сертификат сервера – это ваша обязанность.



Библиотека CLX


Данная часть, вносит некоторый конфуз. До Delphi 7 было следующее разделение:

VCL - Visual Component Library. VCL - библиотека визуальных компонент, что относилось к визуальным компонентам, к не визуальным компонентам и к RTL. CLX (Pronounced "Clicks") - Component Library for Cross Platform - CLX относилось к новой версии кросс платформенной  части VCL, которая базировалась на QT и могла работать как в Linux, так и в Windows.

Теперь же, после выхода Delphi 7, Borland реорганизовал и переопределил значение данного акронима. Это может привести в большое замешательство, по этому примите во внимание. Начиная с Delphi 7 новое назначение следующее:

CLX - CLX относится ко всем компонентам включенным в Delphi, C++ Builder и в Kylix. VCL - VCL относится к визуальным компонентам, которые работают напрямую с Win32 API. Visual CLX - Visual CLX относится к кросс платформенным визуальным компонентам, которые базируются на QT, доступны и в Delphi и в Kylix. VCL for .NET - VCL for .NET относится к новой VCL, которая запускается под .NET и предоставляет слой совместимости для старых приложений и плюс дополнительную функциональность.

Если вы посмотрите на новые определения, я не уверен, что они согласованы. Я думаю в будущем они приведут к будущим недоразумениям. Я думаю NLX (Nelix?), или NCL (Nickel?), или что ни будь еще более more совместимое будет лучшим выбором для VCL .Net. Как видим, Visual CLX – это подмножество от CLX, не VCL for .NET – это родной брат VCL, как и Visual CLX.

Это должно выглядеть так:

VCL --> CLX CLX --> Visual CLX Visual Parts of VCL --> VCL

Хорошо, пусть это все будут мечты.



Библиотека времени исполнения RTL


Библиотека времени исполнения RTL содержит не визуальные низкий уровень классов в Delphi, такие как TList, TStrings и другие.

Библиотека времени исполнения RTL – также доступна и в Delphi .NET. Многое из того, что есть в RTL имеет своих двойников в .NET framework, но предоставив RTL Borland сделал более простым перенос существующего кода, без необходимости переписывать большие куски кода и позволяет создавать кросс платформенный код.



Благодарности


Большая благодарность следующим людям, группам и компаниями:

Indy Pit Crew и Mercury Team за многие часы посвященными ими Indy. Что бы не забыть, многих людей, которые помогали нам с Indy, чьи имена были забыты. ECSoftware за разработку справки и руководство, за продукт Help and Manual, с помощью которого и был написан этот документ http://www.helpandmanual.com

Блокирующий режим


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

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



Блокирующий режим это не смертельно


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

Когда API Unix сокетов было портировано в Windows, то ему дали имя Winsock. Это сокращение от "Windows Sockets".

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

Windows 3.x не мог распараллеливаться и плохо поддерживал многозадачность. Windows 3.1 также не имел поддержки потоков. Использование блокирующих сокетов замораживало пользовательский интерфейс и делало программы не реагирующими. Поскольку это было не приемлемо, то к WinSock были добавлены неблокирующие сокеты, позволяя Windows 3.x с его ограничениями использовать Winsock без замораживания всей системы. Это потребовало другого программирования сокетов, Microsoft и другие страстно поносили блокирующие режимы, что бы скрыть недостатки Windows 3.x.

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

В действительности, блокирующее API единственное которое поддерживает Unix.

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

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



Блокирующий режим записи файла


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

procedure TForm1.Button1Click(Sender: TObject);

var

  s: string;

begin

  s := 'Indy Rules the (Kudzu) World !' + #13#10;

  try

    // Open the file

    with TFileStream.Create('c:\temp\test.dat', fmCreate) do

    try

      // Write data to the file

      WriteBuffer(s[1], Length(s));

      // Close the file

    finally

      Free;

    end;

  end;

end;

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



Борьба (споры) за ресурсы (Contention)


Что же такое точно борьба за ресурсы? Борьба за ресурсы – это когда более чем одна задача пытается получить доступ к одному и тому же ресурсу, в то же самое время.

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

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

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

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



Буферизация записи


TCP должен посылать данные пакетами. Размер пакетов может изменяться, но как правило он немногим менее 1 килобайта. Тем не менее, если TCP ожидает полного пакета данных, во многих случаях ответы могут быть не получены, поскольку запросы не были отосланы. TCP может использовать полные или неполные пакеты, Для неполных пакетов можно использовать алгоритм названый Nagle Coalescing. Nagle Coalescing внутренне буферизует данные, пока не будет достигнут указанный размер пакета или не истечет рассчитанное количество времени. Период времени обычно маленький и измеряется в миллисекундах.

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

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

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

Для начала буферизации записи, вызовите метод OpenWriteBuffer и укажите размер буфера. Затем вы можете вызывать все функции записи в Indy, и весь вывод будет буферизироваться, пока буфер не будет заполнен. Каждый раз когда будет достигнут размер буфера, буфер посылается в соединение и очищается. Если размер буфера не указан, все данные буферизуются и должны быть вручную отправлены.

Имеется также несколько методов для управления буфером.

ClearWriteBuffer очищает текущий буфер и сохраняет буфер открытым. FlushWriteBuffer сбрасывает текущее содержимое и также сохраняет буфер открытым.

Для прекращения буферизации записи, вызовите CancelWriteBuffer или CloseWriteBuffer. CloseWriteBuffer записывает имеющие данные и заканчивает буферизацию записи, а CancelWriteBuffer закрывает буферизацию записи, без передачи.



Цепочки (судя по всему внутренняя абстракция)


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

При использовании цепочки, IOHandler основаный на ней, помещает  операцию в очередь. (От корректора: Какого хрена здесь IOHandler? Мы вроде о волокнах говорим.)

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

Планировщик обслуживает волокна и ожидает окончания их работы.

Драйвер цепочек запрашивает рабочую очередь и взаимодействует с планировщиком.



Chad Z. Hower a.k.a Kudzu


Чад Хувер (Chad Z. Hower), известный так же, как "Kudzu" является автором и координатором проекта Internet Direct (Indy). Indy состоит из более, чем 110 компонент и является частью Delphi, Kylix и C++ Builder. В опыт Чада входит работа с трудоустройством, безопасность, химия, энергетика, торговля, телекоммуникации, беспроводная связь и страховая индустрии. Особая область Чада это сети TCP/IP, программирование, межпроцессорные коммуникации, распределенные вычисления, Интернет протоколы и объектно-ориентированное программирование.

Когда он не занимается программирование, то он любит велосипед, каяк, пешие прогулки, лыжи, водить и просто чем ни будь заниматься вне дома. Чад, чей лозунг "Программирование это искусство а не ремесло", также часто публикует статьи, программы, утилиты и другие вещи на Kudzu World http://www.Hower.org/Kudzu/.

Чад как истинный американский путешественник, проводит свое лето в Санкт-Петербурге, Россия, а зиму в Лимасоле на Кипре.

Чад доступен через Веб форму.

Чад является ведущим разработчиком в Atozed Software.



Чтение и запись


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

Каждый из методов – это подмножество класса TIdTCPConnection. Это зависит от типа каждого серверного соединения и являются наследником TIdTCPClient. Это означает, что вы можете использовать эти методы, как для серверов, так и для клиентов.

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

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

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



Что такое поток?


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

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

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

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



Что выбрать WinForms или VCL for .Net?


Это область для сомнений у пользователей – должен я использовать WinForms или VCL for .NET для разработки GUI?

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

VCL for .Net

WinForms

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

Малый размер дистрибутива, поскольку все сборки входят в состав .NET framework.

Только для платформы Win32.

Возможны подмножества для compact .NET framework for pocket PC's. можно переносить на другие реализации .NET.

Высокая степень совместимости со старым кодом.

Требуются значительные изменения в существующем коде.

Кросс платформенность с VCL for Win32 и с Visual

Только для .Net framework.

CLX for Linux (и Windows).

Более эффективно в некоторых областях.

Не поддерживает всю оптимизацию, которая есть в VCL.

Дополнительные свойства и классы. Это включает дополнительные визуальные органы, но теряются такие вещи как списки действий (action lists), базы данных и многое другое.

Не доступен полный исходный код.

Не доступен исходный код

Другая возможность – вы можете смешивать код. VCL for .NET и WinForms не исключают друг друга и могут сосуществовать в одном приложении.



CIL


Common Intermediate Language или просто Intermediate Language (промежуточный язык). Это язык компилятора, который преобразовывает исходный код, пригодный для использования в рантайм.

IL выполняет роль, подобную P-коду или интерпретируемому языку Java. Но также он отличается от них и реализован совсем иначе.



CLR


CLR – это сокращение от Common Language Runtime. CLR – это основа NET framework и среда исполнения приложений, которые компилируются в IL. Вначале вам может показаться, что CLR очень похожа на интерпретатор P-кода, поскольку выполняет аналогичную роль, но это не интерпретатор простого P-кода, а много больше.



CLS


CLS – это сокращение от Common Language Specification. CLS это просто спецификация, которая определяет, какие свойства языка могут и должны быть поддержаны для работы в .NET.



CTS


CTS CLR – это сокращение от Common Type System. CTS включает предопределенные, базовые .NET типы, которые доступны в любом .NET языке. Это означает, что integer больше не определяется каждым компилятором, а встроен в CTS и поэтому integer полностью одинаков во всех .NET языках.

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

Типы значений - это типы, которые записываются в стеке. Вы должны быть знакомы с термином – простой или порядковый типы. Типы значений включают integers, bytes и другие примитивы, структуры и перечисления.

Ссылочные типы – это типы, значения которых сохраняются в куче, и ссылки используются для доступа к ним. Ссылочные типы включают objects, interfaces и pointers.



Для дальнейшего чтения


Данные книги содержат статьи об Indy.

Building Kylix Applications by Cary Jensen Mastering Delphi by Marco Cantu SDGN Magazine - SDGN Magazine, официальный журнал SDGN, в котором есть постоянная колонка - The Indy Pit Stop written by Chad Z. Hower a.k.a Kudzu.

Дополнения по переносу


Некоторые из дополнений в Delphi .NET очень важны для переноса приложений, а некоторые нет. Данные вещи не являются жизненно важными и поэтому будут рассмотрены очень кратко.



Дополнительные материалы


Данная глава содержит дополнительные материалы, которые напрямую не относится к Indy.



Достоинства блокирующего режима


1. Проще программировать - Блокирующие сокеты проще программировать. Весь пользовательский код может находиться в одном месте и выполняться в естественном, последовательном порядке.

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

3.      Удобнее работать с потоками - Поскольку у блокирующих сокетов последовательность приобретена по наследственности, поэтому их очень просто использовать в потоках.

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



Достоинства неблокирующего режима


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

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

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



Достоинства потоков


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



Драйверы цепочек (chain engines)


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

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

Если больше нет значений в рабочей очереди, то драйвер цепочки переходит в пассивное состояние.

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



Другие дополнения к языку


Delphi.NET also supports many new smaller additions to the language such as static class data, record inheritance, class properties, and more. Most of the enhancements relate to features of classes at the language level.

While useful and required by the CLS, they are not essential in porting applications.



Другие клиенты


SSL может легко реализована в любом TCP клиенте Indy с помощью использования SSL IOHandler. Обычно шифрование должно быть реализовано с помощью Intercept вместо IOHandler. SSL реализация в Indy использует IOHandler вместо Intercept, поскольку SSL библиотека выполняют весь обмен самостоятельно. Данные возвращаются в расшифрованной форме напрямую из SSL библиотеки.

Чтобы сделать Indy TCP клиента с использованием SSL просто добавьте TIdSSLIOHandlerSocket на вашу форму с закладки Indy Misc. затем установите свойство IOHandler вашего TCP клиента в TIdSSLIOHandlerSocket. Это все, что требуется для базовой поддержки SSL. Класс TIdSSLIOHandlerSocket имеет дополнительные свойства для указания сертификатов клиентской стороны и другие расширенные SSL параметры.



Другие модели


В действительности есть еще несколько реализованных моделей. Это completion ports, and overlapped I/O. Но использование этих моделей требует гораздо больше кода и обычно используется только в очень сложных серверных приложениях.

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

Indy 10 содержит поддержку и этих моделей.



Другие ресурсы


Главный Интернет сайт проекта - http://www.Indyproject.org/ Зеркала проекта - http://Indy.torry.NET/ Портал Indy – Подписка на новости, статьи, загрузка примеров. http://www.atozedsoftware.com/Indy/ Kudzu World - Chad Z. Hower уголок в Сети. http://www.hower.org/Kudzu/


Файл Cert.pem


С помощью блокнота создайте файл cert.pem и скопируйте все между двумя, ниже указанными строками:

-----BEGIN CERTIFICATE-----

-----END CERTIFICATE-----



Файл HOSTS


Файл HOSTS это текстовый файл, который содержит локальную информацию об узлах.

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

Это пример файла HOSTS:

# This is a sample HOSTS file

Caesar   192.168.0.4  # Server computer

augustus 192.168.0.5  # Firewall computer

Имя узла и IP адрес должны быть разделены с помощью пробела или табуляции. Комментарии также могут быть вставлены в файл, для этого должен быть использован символ #.

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



Файл Key.pem


С помощью блокнота создайте файл key.pem и скопируйте все между двумя, ниже указанными строками:

-----BEGIN RSA PRIVATE KEY-----

-----END RSA PRIVATE KEY-----



Файл Root.pem


Последний файл, который требуется для Indy – это Certificate Authority certificate файл. Вы можете получить его из Internet Explorer в диалоге Trusted Root Certificate Authority. Выберите поставщика (Authority), чей сертификат вы желаете экспортировать и экспортируйте его в Base64 (cer) формате. Данный формат, аналогичен PEM и после экспорта просто переименуйте его в root.pem



Файл SERVICES


Файл SERVICES подобен файлу HOSTS. Вместо разрешения узлов в IP адреса, он разрешает имена сервисов в номера портов.

Ниже пример, урезанный, файла SERVICES. Для полного списка сервисов вы можете обратиться к RFC 1700. RFC 1700 содержит определение сервисов и их портов:

Echo     7/tcp

Echo     7/udp

Discard  9/tcp        sink null

Discard  9/udp        sink null

Systat  11/tcp        users             #Active users

Systat  11/tcp        users             #Active users

Daytime 13/tcp

Daytime 13/udp

Qotd    17/tcp        quote             #Quote of the day

qotd    17/udp        quote             #Quote of the day

chargen 19/tcp        ttytst source     #Character generator

chargen 19/udp                          ttytst source    #Character generator

ftp-data 20/tcp                          #FTP data

ftp     21/tcp                          #FTP control

telnet  23/tcp

smtp    25/tcp                          mail #Simple Mail Transfer Protocol

Формат файла следующий:

<service name> <port number>/<protocol> [aliases...] [#<comment>]

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

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

gds_db 3050/tcp

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



Файлы против сокетов


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



Fork


Unix до сих пор не имеет поддержки потоков. Вместо этого, Unix использует ветвление (forking). С потоками, каждая отдельная строка выполнения исполняется, но она существует в том же самом процессе, как и другие потоки и в том же адресном пространстве. При разветвлении каждый процесс должен сам себя разделять. Создается новый процесс и все хендлы (handles) передаются ему.

Разветвление не так эффективно как потоки, но также имеется и преимущества. Разветвление более стабильно. В большинстве случаев - разветвление легче программировать.

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



FTP User@Site прокси


Для реализации FTP прокси имеются несколько методов. Основной тип FTP прокси называется User@site.

При использования метода User@Site, все FTP сессии подсоединяются к локальному прокси серверу. Прокси притворяется что он FTP сервер. Прокси сервер перехватывает и интерпретирует FTP запросы. Когда прокси запрашивает имя пользователя, то имя пользователя и нужный FTP посылаются в виде username@ftpsite. Прокси соединяется нужным FTP и перехватывает команды передачи.

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

Например, пусть дан FTP сайт - ftp.atozedsoftware.com и имя пользователя joe, а его пароль smith, то нормальная сессия выглядит так:

Host: ftp.atozedsoftware.com

User: joe

Password: smith

Если User@Site прокси существует и его имя corpproxy, то FTP сессия выглядит так:

Host: corpproxy

User: joe@ftp.atozedsoftware.com

Password: smith



Функция AllData


function AllData: string;

Функция AllData блокирует и собирает все входящие данные, до разъединения соединения. Затем возвращает все собранные данные в качестве результата. AllData полезен для протоколов аналогичным WhoIs, после получения запроса, возвращает данные и сигнал, что соединение прекращено. AllData хранит свои буферы в оперативной памяти, поэтому не стоит использовать ее для больших по размеру данных.



Функция CurrentReadBuffer


function CurrentReadBuffer: string;

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

Если данных нет, то возвращается пустая строка.



Функция InputLn


function InputLn(const AMask: String = ''; AEcho: Boolean = True; ATabWidth: Integer = 8; AMaxLineLength: Integer = -1): String;

Функция InputLn читает строку от сервере и возвращает е обратно reads a line from the server and echoes it back honoring the backspace character. Если параметр AMask указан, то строка AMask отсылается вместо каждого принятого символ. Функция InputLn полезна, когда вы не желаете отображать принятые символы, например пароль.



Функция ReadCardinal


function ReadCardinal(const AConvert: boolean = true): Cardinal;

Функция ReadCardinal читает 32-битное число без знака из соединения, с дополнительным учетом сетевого порядка байт.



Функция ReadFromStack


function ReadFromStack(const ARaiseExceptionIfDisconnected: Boolean = True; ATimeout: Integer = IdTimeoutDefault;

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



Функция ReadInteger


function ReadInteger(const AConvert: boolean = true): Integer;

Функция ReadInteger читает r 32-битное число со знаком из соединения, с дополнительным учетом сетевого порядка байт.



Функция ReadLn


function ReadLn(ATerminator: string = LF; const ATimeout: Integer = IdTimeoutDefault; AMaxLineLength: Integer = -1): string; virtual;

Функция ReadLn читает данные из соединения, пока не встретит указанный ограничитель, в течение периода таймаута или в случае приема указанной максимальной длины строки.



Функция ReadLnWait


function ReadLnWait(AFailCount: Integer = MaxInt): string;

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



Функция ReadSmallInt


function ReadSmallInt(const AConvert: Boolean = true): SmallInt;

Функция ReadSmallInt читает короткое целое из соединения, дополнительно делая подстройку под сетевой порядок байт.