В одной из статей, посвященных использованию библиотеки Synapse в Delphi, я рассматривал одно из событий объекта TTCPBlockSocket — OnStatus. Сегодня я более подробно расскажу о том какие ещё события можно использовать в работе с Synapse и какую информацию мы можем получить.
Кстати, прежде, чем мы начнем рассмотрение вопроса — советую Вам обновить библиотеку из репозитория. В обновленной версии (на момент написания поста последняя была ревизия № 129) исправлены кое-какие недочеты и ошибки и библиотека стала работать немного по-шустрее и значительно уменьшено количество сообщений [warning] компилятора, что не может не радовать.
Итак, начнем рассмотрение вопроса с уже более-менее знакомого нам события OnStatus.
Событие OnStatus
property OnStatus: THookSocketStatus read FOnStatus write FOnStatus;
Это событие, можно сказать, практически универсальное и может использоваться в зависимости от различных ситуаций и требования, например, для мониторинга трафика, проходящего через сокет, создание сокета и его уничтожение и т.д.
Процедурный тип для события OnStatus выглядит следующим образом:
THookSocketStatus = procedure(Sender: TObject; Reason: THookSocketReason; const Value: String) of object;
Sender: TObject — объект-отправитель сообщения. В нашем случае — это TTCPBlockSocket.
Reason: THookSocketReason — тип события.
Value: String — значение, возвращаемое сокетом при возникновении разных типов событий. При этом разработчик сам должен обеспечить приведение значения value к необходимому типу.
Рассмотрим, какие значения будет возвращать нам сокет в зависимости от значение параметра Reason.
Reason |
Описание |
Value должен приводится к |
Описание |
HR_ResolvingBegin | Начало определения параметров соединения |
string |
Возврашает адрес в формате: host:portнапример, www.webdelphi.ru:80 |
HR_ResolvingEnd | Окончание определения параметров соединения |
string |
Возвращает адрес в формате: host:port или IP-адрес:portнапример, www.webdelphi.ru:80 или 217.199.213.171:80 |
HR_SocketCreate | Socket создан методом CreateSocket. | string |
Возвращает семейство соккетов, например, IPv4 |
HR_SocketClose | Socket закрыт методом CloseSoket. |
— |
— |
HR_Bind | Socket связан с IP-адресом по заданному порту |
string |
Парметры соединения в формате host:portнапример, www.webdelphi.ru:80 |
HR_Connect | Socket соединен с IP-адресом по заданному порту |
string |
Парметры соединения в формате host:portнапример, www.webdelphi.ru:80 |
HR_CanRead | Socket готов принимать данные. Метод CanRead вернул True. |
— |
— |
HR_CanWrite | Socket готов отправить данные. Метод CanWrite вернул True. |
— |
— |
HR_Listen | Socket перешел в режим прослушивания (Только для TCP-сокетов) |
— |
— |
HR_Accept | Socket принял попытку соединения клиента (Только для TCP-сокетов) | — |
— |
HR_ReadCount | Сообщает сколько байт информации было получено. |
integer |
Количество байт информации, например,1024 |
HR_WriteCount | Сообщает сколько байт информации было отправлено. |
integer |
Количество байт информации, например,1024 |
HR_Wait | Превышен лимит пропускной способности канала и Socket находится в режиме ожидания |
integer |
Количество миллисекунд ожидания, например,1000 |
HR_Error | Сообщает о том, что во время выполнения операции произошла ошибка |
— |
— |
Как видно из представленной выше таблицы в трех случаях в параметре Value возвращается строка, которую при необходимости нам надо привести к типу integer.
Пример использования события OnStatus:
uses ... TypInfo; type TForm4 = class(TForm) ... procedure FormCreate(Sender: TObject); ... private { Private declarations } public HTTP: THTTPSend; //объект THTTPSend для работы с HTTP-протоколом procedure Status(Sender: TObject; Reason: THookSocketReason; const Value: String);//обработчик события OnStatus сокета end; var Form4: TForm4; implementation .... procedure TForm4.Status(Sender: TObject; Reason: THookSocketReason; const Value: String); begin ShowMessage(GetEnumName(TypeInfo(THookSocketReason),ord(Reason))+' '+Value); end; procedure TForm4.FormCreate(Sender: TObject); begin HTTP:=THTTPSend.Create;//создаем объект HTTP.Sock.OnStatus:=Status;//определяем обработчик end;
В приведенном выше примере мы будем получать сообщение каждый раз, когда socket совершит какое-либо действие и сменит свой статус.
Событие OnReadFilter
property OnReadFilter: THookDataFilter read FOnReadFilter write FOnReadFilter;
Это событие можно использовать для фильтрации получаемых сокетом данных.
Процедурный тип для события OnReadFilter:
THookDataFilter = procedure(Sender: TObject; var Value: AnsiString)
Value: string — возвращает информацию, полученную сокетом, например, часть документа. Посмотрим как можно использовать это событие для своих целей. В приведенном ниже примере текст документа автоматически конвертируется из UTF8 в Ansi:
procedure TForm4.FormCreate(Sender: TObject); begin .... HTTP.Sock.OnReadFilter:=HookDataFilter; end; procedure TForm4.HookDataFilter(Sender: TObject; var Value: AnsiString); begin Memo1.Lines.Add('---------------'); Memo1.Lines.Add(Utf8ToAnsi(Value)); end;
Приведенный пример лишь демонстрирует работц с событием. В реальных условиях написания программ не желательно использовать это событие для таких обычных моментов как смена кодировки или удаление тегов и т.д., т.к. в этом случае мы затрачиваем каждый раз дополнительное время на выполнение операций в обработчике события. Более подробный пример использования этого события Вы можете посмотреть в клиенте Telnet Synaps’а.
Событие OnMonitor
property OnMonitor: THookMonitor read FOnMonitor write FOnMonitor;
Это событие, по задумке разработчиков, удобно использовать для мониторинга прочитанных или отправленных через соккет данных.
Процедурный тип для события:
THookMonitor = procedure(Sender: TObject; Writing: Boolean; const Buffer: TMemory; Len: Integer) of object;
Writing:boolean — true указывает на то, что сокет отправляет данные.
Buffer: TMemory — указатель наобласть памяти в которой расположены данные.
Len: integer — размер отправленых/полученых данных (за одну операцию чтени/отправки)
По большому счёту это событие является чем-то средним между OnStatus и OnReadFilter. С помощью этого события удобно определять размеры полученных и отправленных данных, не прибегая к анализу Reason, а также, в случае необходимости, узнать что именно мы прочитали.
В представленном ниже примере в Memo1 будут выводится части прочитанной страницы сайта, разделенные пустой строкой:
procedure TForm4.HookMonitor(Sender: TObject; Writing: Boolean; const Buffer: TMemory; Len: Integer); begin Memo1.Lines.Add(' '); Memo1.Lines.Add(String(Buffer)) end; procedure TForm4.FormCreate(Sender: TObject); begin HTTP:=THTTPSend.Create; ... HTTP.Sock.OnMonitor:=HookMonitor; end;
Событие OnHeartbeat
property OnHeartbeat: THookHeartbeat read FOnHeartbeat write FOnHeartbeat;
«Сердцебиение» сокета. Это событие удобно использовать при выполнении длительных операций без использования потоков. Время срабатывания события можно настроить с помощью свойства HeartbeatRate.
По умолчанию HeartbeatRate = 0, т.е. «сердцебиение» отключено. Время срабатывания события задается в миллисекундах. При использовании OnHeartbeat необходимо учитывать два момента:
- Выполнения этого события замедляет работу сокета.
- Событие может вызываться чаще или наоборот — реже, чем задано в параметре HeartbeatRate. То есть HeartbeatRate в данном случае является чем-то вроде средней величины времени срабатывания события.
Процедурный тип для события:
THookHeartbeat = procedure(Sender: TObject) of object;
В обработчике события можно проводить какие-либо операции с сокетом, например, проверить состояние буфера для приема данных, запросить какие-либо данные по состоянию сокета и т.д. — все, что вам угодно.
События OnCreateSocket и OnAfterConnect
Два события возникающие соответственно при создании сокета и после того как сокет установил соединение с хостом. Процедурные типы для этих событий абсолютно идентичны:
THookCreateSocket = procedure(Sender: TObject) of object; THookAfterConnect = procedure(Sender: TObject) of object;
Эти события можно использовать, например, для установления каких-либо свойств сокета не по умолчанию.
Вот шесть возможных событий, которые Вы можете использовать при работе с HTTP-протоколом с использованием Synapse и, в частности, с THTTPSend и TTCPBlockSocket. В качестве заключения скажу, что если Вам необходимо получить размер отправленных/полученных данных, то лучше использовать событие OnMonitor, т.к. оно срабатывает реже, чем OnStatus и несет для Вас в данном случае целевую информацию. С другой стороны, если Вы хотите вести полный лог работы сокета, то тут надо использовать OnStatus. С особой осторожностью следует работать с «сердцебиением», т.к. это событие может очень сильно снизить скорость работы Вашего приложения с Сетью.
Книжная полка
Описание: Рассмотрены практические вопросы по разработке клиент-серверных приложений в среде Delphi 7 и Delphi 2005 с использованием СУБД MS SQL Server 2000, InterBase и Firebird. Приведена информация о теории построения реляционных баз данных и языке SQL. Освещены вопросы эксплуатации и администрирования СУБД.
|
||
Название: О чем не пишут в книгах по Delphi
Описание: Рассмотрены малоосвещенные вопросы программирования в Delphi. Описаны методы интеграции VCL и API. Показаны внутренние механизмы VCL и приведены примеры вмешательства в эти механизмы. Рассмотрено использование сокетов в Delphi: различные режимы их работы, особенности для протоколов TCP и UDP и др.
|