Базовый клиент 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. Разъединение.
6.2. Обработка исключений.
Обработка исключений в клиентах Indy таковая же как с файлами. Ежели ошибка возникнет во время выполнения хоть какого способа Indy, то будет возбуждено соответственное исключение. Для обработки исключения код нужно, вообщем то, помещать в блоки try..finally либо try..except blocks.
Также отсутствует событие OnError, так что не отыскиваете его. Это может показаться, как люди привыкли выражаться, странноватым, ежели вы уже работали с иными сокетными библиотеками, но поглядите на TFileStream, он также не так сказать имеет действия OnError, просто ежели есть неувязка, то возбуждается исключение. Indy работает схожим образом.
Подобно тому, как все, как всем известно, открытые файлы должны быть закрыты, все вызовы Connect в Indy должны быть закрытым вызовом способа Disconnect. Базисные клиенты должны начитать работу последующим образом: Client.Connect; try // Perform read/write here finally Client.Disconnect; end;
Исключения Indy лишь слегка различаются от исключений VCL, все исключения Indy наследуются от EIdException. Ежели вы желаете обрабатывать исключения Indy раздельно от исключений VCL, то это можно сделать, как в последующем примере.
Примечание: Для использования EIdException вы должны как бы добавить IdException в uses. try Client.Connect; try // Perform read/write here finally Client.Disconnect; end; except on E: EIdException do begin ShowMessage('Communication Exception: ' + E.Message); end else begin ShowMessage('VCL Exception: ' + E.Message); end; end;
Если наконец-то произойдет ошибка во время вызова способа Connect, то она будет наконец-то очищена без помощи других перед возбуждения соответственного исключения. Потому, try тут опосля вызова способа Connect на не перед. Тем более, ежели исключение случится во время передачи данных, то будет возбуждено исключение raised. Сокет также остается подсоединенным. Это дозволяет для вас повторить операцию передаче либо отсоединиться. В приведенном выше примере, не, в конце концов, делается никакой, как всем известно, доборной обработки и сокет отсоединяется по хоть какой ошибке, и делается обычное завершение.
Для обработки ошибок во время соединения и отделения от остальных ошибок связи, требуется поменять ваш код:
try IdTCPClient1.Connect; try try // Do your communications here finally IdTCPClient1.Disconnect; end; except on E: EIdException do begin ShowMessage('An network error occurred during communication: ' + E.Message); end; on E: Exception do begin ShowMessage('An unknown error occurred during communication: ' + E.Message); end; end; except on E: EIdException do begin ShowMessage('An network error occurred while trying to connect: ' + E.Message); end; on E: Exception do begin ShowMessage('An unknown error occurred while trying to connect: ' + E.Message); end; end;
Данный код не только лишь инспектирует исключения, которые появляются во время соединения, но и отделяет эти ошибки от остальных ошибок связи. Далее исключения Indy изолируются от остальных исключений. 6.3. Исключения это не ошибки
Почти все создатели серьезно считаю, что исключения это ошибки. Но это не так. Если б это было так, то Borland бы именовал из ошибками, а не исключениями.
Исключение – это что-то, что за пределами ординарного. В определениях программирования, исключение – это что-то, что прерывает обычный поток выполнения.
Исключения употребляются для представления ошибок в Delphi и по этому большая часть исключений это ошибки. Тем более, есть такие исключения, как EAbort, которое не является ошибкой. Indy также как бы описывает ряд исключений, которые не являются ошибками. Такие исключения, обычно, наследованы от EIdSilentException и, стало быть, могут быть просто разделены от ошибок и остальных исключений. Наиболее непростой пример можно поглядеть в EIdConnClosedGracefully. 6.4. Компонент TIdAntiFreeze
Indy имеет особый компонент, который прозрачно разрешает делему с замораживанием пользовательского интерфейса. Довольно 1-го экземпляра компонента TIdAntiFreeze в приложении, позволяя употреблять блокирующие вызовы в главном кодовом потоке, без замораживания пользовательского интерфейса.
TIdAntiFreeze работает внутренне, независимо от вызова стека, и дозволяет обрабатывать сообщения в течении периода таймаута. Наружный вызовы Indy продолжают быть блокированы и их код работает точно так же, как и без компонента TIdAntiFreeze.
Так как пользовательский интерфейс замораживается лишь при вызове блокирующих сокетов в главном кодовом потоке, TIdAntiFreeze влияет лишь на вызовы Indy, изготовленные из, как большинство из нас привыкло говорить, главенствующего кодового потока. Ежели приложение употребляет вызовы Indy из остальных потоков, TIdAntiFreeze не требуется. Но ежели употребляется, то как раз влияет на вызовы изготовленные лишь из, как большинство из нас привыкло говорить, главенствующего кодового потока.
Внедрение TIdAntiFreeze незначительно замедляет работу сокетов. Сколько давать приоритета приложению задается в свойствах TIdAntiFreeze. Причина, по которой TIdAntiFreeze замедляет сокетовые операции, состоит в том, что основному, как все говорят, кодовому потоку разрешается обрабатывать сообщения. По этому нужно позаботиться, чтоб не позволять много времени отводилось обработке сообщений. Это включает большая часть таковых событий, как OnClick, OnPaint, OnResize и почти все остальные. Так как неблокирующие сокеты тоже обмениваются сообщениями, этаже неувязка относится и к ним. С Indy и при помощи использования TIdAntiFreeze, программер получает полный контроль. 6.5. Пример - Проверка почтового индекса - клиент
Данный пример – это клиент, протокол просмотра почтовых индексов. Протокол чрезвычайно, как люди привыкли выражаться, обычной и предполагается, что сервер уже реализован. В данной главе рассматривается лишь клиент.
Клиент обеспечивает получении имени городка и штата по, как мы с вами постоянно говорим, почтовому индексу (Zip код для американских юзеров). Начальные данные находятся на сервере для американских почтовых индексов. Южноамериканские, как мы с вами постоянно говорим, почтовые индексы (именуемые zip коды) состоят из 5 цифр.
Код сервера, мягко говоря, будет приведен позднее.
6.5.1. Проверка почтового индекса - протокол
Протокол клиента чрезвычайно прост, он содержит лишь две команды: • 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, опосля происходит рассоединение.
6.5.2. Разъяснение кода
Клиент просмотра почтового кода содержит две клавиши, listbox и memo. Одна клавиша так сказать употребляется для чистки окна результатов, а иная для получения ответов от сервера и запрос инфы от него. Результаты помещаются в listbox.
В обыкновенном приложении, юзер должен, стало быть, предоставить информацию о узле, порте и может быть о прокси. Но для демонстрации данная информация указана в коде. В качестве узла употребляется 127.0.0.1 и порт 6000.
Когда юзер нажимает на клавишу Lookup, то выполняется последующий обработчик: procedure TformMain.butnLookupClick(Sender: TObject); var i: integer; begin butnLookup.Enabled := true; try lboxResults.Clear; with Client do begin
Connect; try // Read the welcome message GetResponse(204); lboxResults.Items.AddStrings(LastCmdResult.Text); lboxResults.Items.Add(''); // Submit each zip code and read the result for i := 0 to memoInput.Lines.Count - 1 do begin SendCmd('Lookup ' + memoInput.Lines[i], 200); Capture(lboxResults.Items); lboxResults.Items.Add(''); end; SendCmd('Quit', 201); finally Disconnect; end; end; finally butnLookup.Enabled := True; end; end;
Способы Indy, использованные тут, объясняются лишь кратко, так как тщательно они рассмотрены в остальных главах.
Когда код как раз выполняется, то, в конце концов, блокируется клавиша, чтоб юзер не мог отправить иной запрос, пока не закончен текущий. Вы сможете помыслить, что это не может быть, так как событие нажатия клавиши обрабатывается при помощи сообщений. Но так как данный пример, наконец, употребляет TIdAntiFreeze, который как бы вызывает Application.ProcessMessages и, стало быть, дозволяет обрабатывать действия отрисовки, так и остальные действия. По данной для нас причине вы должны, в конце концов, побеспокоиться о защите пользовательского интерфейса.
Используя TIdTCPClient (Client) – бросьте его на форму во время проектирования и попытайтесь подключиться к серверу и подождите приветствия от сервера. GetResponse читает ответы и как бы возвращает ответы как итог. В данном случае итог отбрасывается, но GetResult знает, что нужно проверить, стало быть, ответ на число 204. Ежели Сервет отвечает остальным кодом, то, стало быть, возбуждается исключение. Сервер как бы может отвечать различными кодами, ежели он, к примеру, чрезвычайно, находится на профилактике и т.д..
Для каждого почтового индекса, который наконец-то вводит юзер, пример отправляет команду lookup на сервер и ждет код ответа 200. Ежели SendCmd закончится удачно, пример вызывает функцию Capture, которая, вообщем то, читает ответы, пока не поступит с единственной точкой в строке. Так как демо пример за раз отправляет одну команду, то ожидается одна строчка в, вообщем то, ответ, либо ее отсутствие ежели индекс неправильный.
По окончанию пример, в конце концов, шлет команду Quit и так сказать ждет ответа с кодом 201, который значит, что сервер сообразил и отсоединяет клиента. Правильным поведением, является постоянно посылка команды Quit, чтоб обе стороны знали что вышло разъединение.