Читаем О чём не пишут в книгах по Delphi полностью

Дескрипторы событий, взведения которых ожидает нить, должны храниться в массиве, размер которого передаётся через параметр cEvents, а указатель — через параметр lphEvents. Параметр fWaitAll определяет, что является условием окончания ожидания: если он равен True, ожидание завершается, когда все события из переданного массива оказываются во взведенном состоянии, если False — когда оказывается взведенным хотя бы одно из них. Параметр dwTimeout определяет тайм-аут ожидания в миллисекундах. В WinSock 2 определена константа WSA_INFINITE (совпадающая по значению со стандартно константой INFINITE), которая задает бесконечное ожидание. Параметр fAlertable нужен при перекрытом вводе-выводе: мы рассмотрим его позже в разд. 2.2.9. Если перекрытый ввод-вывод не используется, fAlertable должен быть равен False.

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

Результат, возвращаемый функцией, позволяет определить, по каким причинам закончилось ожидание. Если ожидалось взведение всех событий (fWaitAll = True), и оно произошло, функция возвращает WSA_WAIT_EVENT_0 (0). Если ожидалось взведение хотя бы одного из событий, возвращается WSA_WAIT_EVENT_0 + Index, где Index — индекс взведенного события в массиве lphEvents (отсчет индексов начинается с нуля). Если ожидание завершилось по тайм-ауту, возвращается значение WSA_WAIT_TIMEOUT (258). И наконец, если произошла какая-либо ошибка, функция возвращает WSA_WAIT_FAILED ($FFFFFFFF).

Существует еще одно значение, которое может возвратить функция WSAWaitForMultipleEvents: WAIT_IO_COMPLETION (это константа из стандартной части Windows API, она объявлена в модуле Windows). Смысл этого результата и условия, при которых он может быть возвращен, мы рассмотрим в разд. 2.2.9.

Функции, которые мы рассматривали до сих пор, являются аналогами системных функций для стандартных событий. Теперь мы переходим к рассмотрению тех функций, которые отличают сокетные события от стандартных. Главная из них — WSAEventSelect, позволяющая привязать события, создаваемые с помощью WSACreateEvent, к тем событиям, которые происходят на сокете. Прототип этой функции приведен в листинге 2.59.

Листинг 2.59. Функция WSAEventSelect

// ***** Описание на C++ *****

int WSAEventSelect(SOCKET s, WSAEVENT hEventObject, long lNetworkEvents);

// ***** описание на Delphi *****

function WSAEventSelect(S: TSocket; hEventObject: TWSAEvent; lNetworkEvents: LongInt): Integer;

Эта функция очень похожа на функцию WSAAsyncSelect, за исключением того, что события FD_XXX привязываются не к оконным сообщениям, а к сокетным событиям. Параметр S определяет сокет, события которого отслеживаются, параметр hEventObject — событие, которое должно взводиться при наступлении отслеживаемых событий, lNetworkEvents — комбинация констант FD_XXX, определяющая, с какими событиями на сокете связывается событие hSocketEvent.

Функция WSAEventSelect возвращает ноль, если операция прошла успешно, и SOCKET_ERROR при возникновении ошибки.

Событие, связанное с сокетом функцией WSAEventSelect, взводится при тех же условиях, при которых в очередь окна помещается сообщение при использовании WSAAsyncSelect. Так, например, функция recv взводит событие, если после ее вызова в буфере сокета еще остаются данные. Но, с другой стороны, функция recv не сбрасывает событие, если данных в буфере сокета нет. А поскольку сокетные события не сбрасываются автоматически функцией WSAWaitForMultipleEvents, программа всегда должна сбрасывать события сама. Так, при обработке FD_READ наиболее типична ситуация, когда сначала сбрасывается событие, а потом вызывается функция recv, которая при необходимости снова взводит событие. Здесь мы снова имеем проблему ложных срабатываний в тех случаях, когда данные извлекаются из буфера по частям с помощью нескольких вызовов recv, но в данном случае проблему решить легче: не нужно отменять регистрацию событий, достаточно просто сбросить событие непосредственно перед последним вызовом recv.

Перейти на страницу:

Похожие книги

1С: Управление торговлей 8.2
1С: Управление торговлей 8.2

Современные торговые предприятия предлагают своим клиентам широчайший ассортимент товаров, который исчисляется тысячами и десятками тысяч наименований. Причем многие позиции могут реализовываться на разных условиях: предоплата, отсрочка платежи, скидка, наценка, объем партии, и т.д. Клиенты зачастую делятся на категории – VIP-клиент, обычный клиент, постоянный клиент, мелкооптовый клиент, и т.д. Товарные позиции могут комплектоваться и разукомплектовываться, многие товары подлежат обязательной сертификации и гигиеническим исследованиям, некондиционные позиции необходимо списывать, на складах периодически должна проводиться инвентаризация, каждая компания должна иметь свою маркетинговую политику и т.д., вообщем – современное торговое предприятие представляет живой организм, находящийся в постоянном движении.Очевидно, что вся эта кипучая деятельность требует автоматизации. Для решения этой задачи существуют специальные программные средства, и в этой книге мы познакомим вам с самым популярным продуктом, предназначенным для автоматизации деятельности торгового предприятия – «1С Управление торговлей», которое реализовано на новейшей технологической платформе версии 1С 8.2.

Алексей Анатольевич Гладкий

Финансы / Программирование, программы, базы данных