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

В одной из статей, посвященных использованию библиотеки Synapse в Delphi, я рассматривал одно из событий объекта TTCPBlockSocketOnStatus. Сегодня я более подробно расскажу о том какие ещё события можно использовать в работе с 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.

Значение параметра 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 необходимо учитывать два момента:

  1. Выполнения этого события замедляет работу сокета.
  2. Событие может вызываться чаще или наоборот — реже, чем задано в параметре 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 и др.
купить книгу delphi на ЛитРес
0 0 голоса
Рейтинг статьи
уважаемые посетители блога, если Вам понравилась, то, пожалуйста, помогите автору с лечением. Подробности тут.
Подписаться
Уведомить о
0 Комментарий
Межтекстовые Отзывы
Посмотреть все комментарии