Чтение онлайн

на главную

Жанры

О чём не пишут в книгах по Delphi

Григорьев Антон Борисович

Шрифт:

TWSANetworkEvents = packed record

 lNetworkEvents: LongInt;

 iErrorCode: array[0..FD_MAX_EVENTS - 1] of Integer;

end;

Константа

FD_MAX_EVENTS
определяет количество разных типов событий и в данной реализации равна 10.

Значения констант

FD_XXX
представляют собой степени двойки, поэтому их можно объединять операцией арифметического ИЛИ без потери информации. Поле
lNetworkEvents
является таким объединением всех констант, задающих события,
которые происходили на сокете. Другими словами, если результат операции (
lNetworkEvents and FD_XXX
) не равен нулю, значит, событие
FD_XXX
происходило на сокете.

Массив

iErrorCode
содержит информацию об ошибках, которыми сопровождались события
FD_XXX
. Для каждого события
FD_XXX
определена соответствующая константа
FD_XXX_BIT
(т.е. константы
FD_READ_BIT
,
FD_WRITE_BIT
и т.д.). Элемент массива с индексом
FD_XXX_BIT
содержит информацию об ошибке, связанной с событием
FD_XXX
. Если операция прошла успешно, этот элемент содержит ноль, в противном случае — код ошибки, которую в аналогичной ситуации вернула бы функция
WSAGetLastError
после выполнения соответствующей операции на синхронном сокете.

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

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

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

WSASetEvent
. Это дает нити, вызвавшей функцию
WSAWaitForMultipleEvents
, возможность выходить из состояния ожидания не только при возникновении событий на сокете, но и по сигналам от других нитей. Типичная область применения этой возможности — для тех случаев, когда программа может как отвечать на запросы от удаленного партнера, так и отправлять ему что-то по собственной инициативе. В этом случае могут использоваться два сокетных события: одно связывается с событием
FD_READ
для оповещения о поступлении данных, а второе не связывается ни с одним из событий
FD_XXX
, а устанавливается другой нитью тогда, когда необходимо отправить сообщение. Нить, работающая с сокетом, ожидает взведения одного из этих событий и в зависимости от того, какое из них взведено, читает или отправляет данные.

В листинге 2.62 приведен пример кода такой нити. Она задействует три сокетных события: одно для уведомления о событиях на сокете, второе — для уведомления о необходимости отправить данные, третье — для уведомления о необходимости завершиться. В данном примере мы предполагаем, что, во-первых, сокет создан и подключен до создания нити и передается ей в качестве параметра, а во-вторых, три сокетных события хранятся в глобальном массиве

SockEvents: array[0..2] of TWSAEvent
, причем нулевой элемент этого массива содержит событие, связываемое с событиями
FD_XXX
,
первый элемент — событие отправки данных, второй — событие завершения нити. Прототип функции, образующей нить, совместим с функцией
BeginThread
из модуля
SysUtils
.

Листинг 2.62. Схема нити, использующей события асинхронного сокета

function ProcessSockEvents(Parameter: Pointer): Integer;

var

 S: TSocket;

 NetworkEvents: TWSANetworkEvents;

begin

 // Так как типы TSocket и Pointer занимают по 4 байта, такое

 // приведение типов вполне возможно, хотя и некрасиво

 S := TSocket(Parameter);

 // Связываем событие SockEvents[0] с FD_READ и FD_CLOSE

 WSAEventSelect(S, SockEvents[0], FD_READ or FD_CLOSE);

 while True do

 begin

case WSAWaitForMultipleEvents(3, @SockEvents[0], True, WSA_INFINITE, False) of

WSA_WAIT_EVENT_0: begin

WSAEnumNetworkEvents(S, SockEvents[0], NetworkEvents);

if NetworkEvents.lNetworkEvents and FD_READ > 0 then

if NetworkEvents.iErrorCode[FD_READ_BIT] = 0 then

begin

// Пришли данные, которые нужно прочитать

end

else

begin

// произошла ошибка. Нужно сообщить о ней и завершить нить

closesocket(3);

Exit;

end;

if NetworkEvents.lNetworkEvents and FD_CLOSE > 0 then

begin

// Связь разорвана

if NetworkEvents.iErrorCode[FD_CLOSE_BIT] = 0 then begin

// Связь закрыта корректно

end

else

begin

// Связь разорвана в результате сбоя сети

end;

// В любом случае нужно закрыть сокет и завершить нить

closesocket(S);

Exit;

end;

end;

WSA_WAIT_EVENT_0 + 1: begin

// Получен сигнал о необходимости отправить данные

// Здесь должен быть код отправки данных

// После отправки событие нужно сбросить вручную

ResetEvent(SockEvents[1]);

end;

WSA_WAIT_EVENT_0 + 2: begin

// Получен сигнал о необходимости завершения работы нити

Поделиться:
Популярные книги

Замуж второй раз, или Ещё посмотрим, кто из нас попал!

Вудворт Франциска
Любовные романы:
любовно-фантастические романы
5.00
рейтинг книги
Замуж второй раз, или Ещё посмотрим, кто из нас попал!

Протокол "Наследник"

Лисина Александра
1. Гибрид
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Протокол Наследник

Сердце Дракона. Том 11

Клеванский Кирилл Сергеевич
11. Сердце дракона
Фантастика:
фэнтези
героическая фантастика
боевая фантастика
6.50
рейтинг книги
Сердце Дракона. Том 11

Вперед в прошлое!

Ратманов Денис
1. Вперед в прошлое
Фантастика:
попаданцы
5.00
рейтинг книги
Вперед в прошлое!

Шесть принцев для мисс Недотроги

Суббота Светлана
3. Мисс Недотрога
Фантастика:
фэнтези
7.92
рейтинг книги
Шесть принцев для мисс Недотроги

Хочу тебя любить

Тодорова Елена
Любовные романы:
современные любовные романы
5.67
рейтинг книги
Хочу тебя любить

Огни Аль-Тура. Желанная

Макушева Магда
3. Эйнар
Любовные романы:
любовно-фантастические романы
эро литература
5.25
рейтинг книги
Огни Аль-Тура. Желанная

Начальник милиции 2

Дамиров Рафаэль
2. Начальник милиции
Фантастика:
попаданцы
альтернативная история
5.00
рейтинг книги
Начальник милиции 2

Мастер...

Чащин Валерий
1. Мастер
Фантастика:
героическая фантастика
попаданцы
аниме
6.50
рейтинг книги
Мастер...

Сумеречный стрелок 8

Карелин Сергей Витальевич
8. Сумеречный стрелок
Фантастика:
городское фэнтези
попаданцы
альтернативная история
аниме
5.00
рейтинг книги
Сумеречный стрелок 8

Я до сих пор не князь. Книга XVI

Дрейк Сириус
16. Дорогой барон!
Фантастика:
юмористическое фэнтези
попаданцы
аниме
5.00
рейтинг книги
Я до сих пор не князь. Книга XVI

Обыкновенные ведьмы средней полосы

Шах Ольга
Любовные романы:
любовно-фантастические романы
5.00
рейтинг книги
Обыкновенные ведьмы средней полосы

Метаморфозы Катрин

Ром Полина
Фантастика:
фэнтези
8.26
рейтинг книги
Метаморфозы Катрин

Идеальный мир для Социопата

Сапфир Олег
1. Социопат
Фантастика:
боевая фантастика
рпг
постапокалипсис
6.17
рейтинг книги
Идеальный мир для Социопата