Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Скачиваний:
22
Добавлен:
13.02.2015
Размер:
25 Кб
Скачать

WsaRecv — на событиях

Для использования этого режима при вызове функции WSARecv параметр lpCompletionRoutine должен быть равен NULL, а через параметр lpOverlapped передаётся указатель на структуру WSAOverlapped

typedef struct _WSAOVERLAPPED {

DWORD Internal;

DWORD InternalHigh;

DWORD Offset;

DWORD OffsetHigh;

WSAEVENT hEvent;

} WSAOVERLAPPED, *LPWSAOVERLAPPED;

Поле hEvent задаёт событие, которое будет взведено при завершении операции перекрытого ввода-вывода.

Если на момент вызова функции WSARecv данные в буфере сокета отсутствуют, она вернёт значение Socket_Error, а функция WSAGetLastError -

WSA_IO_Pending (Это значит, что операция начала выполняться в фоновом режиме)

Как только запрос будет выполнен, в буферах, переданных через параметр lpBuffers, оказываются принятые данные, НО

- не знаем размера данных

- быть может операция завершилась с ошибкой

Для получения недостающей информации служит функция WSAGetOverlappedResult:

BOOL WSAGetOverlappedResult(

SOCKET s,

LPWSAOVERLAPPED lpOverlapped,

LPDWORD lpcbTransfer,

BOOL fWait,

LPDWORD lpdwFlags);

Через параметр cbTransfer возвращается количество полученных байт

Может быть вызвана до завершения операции перекрытого ввода-вывода:

Если fWait==TRUE, то блокируем нить, иначе с ошибкой WSA_IO_Incomplete

Функция WSAGetOverlappedResult возвращает True, если операция перекрытого ввода-вывода успешно завершена, и False, если произошли какие-то ошибки

Новая операция перекрытого ввода-вывода может быть начата до того, как закончится предыдущая. Это может быть удобно при работе с несколькими сокетами: можно выполнять операции с ними параллельно в фоновом режиме, получая уведомления о завершении каждой из операций.

Перекрытый ввод-вывод с использованием процедур завершения

void CALLBACK CompletionROUTINE(

DWORD dwError,

DWORD cbTransferred,

LPWSAOVERLAPPED lpOverlapped,

DWORD dwFlags);

Вместо взведения события при завершении операции будет вызвана процедура, указанная в качестве параметра функции WSARecv

Указатель структуру, заданный при вызове WSARecv, передаётся в процедуру завершения через параметр lpOverlapped

Процедура завершения всегда выполняется в той нити, которая инициировала начало

операции перекрытого ввода-вывода.

Но система не может прерывать нить для выполнения процедуры завершения в любой удобный ей момент - нить должна перейти в состояние ожидания.

В это состояние нить можно перевести, например, с помощью функции SleepEx

DWORD SleepEx( DWORDdwMilliseconds; BOOL bAlertable)

Если bAlertable равен True, нить может быть выедена системой из состояния ожидания раньше, чем истечёт заданное время, если возникнет необходимость выполнить

процедуру завершения

О причине завершения ожидания программа может судить по результату, возвращаемому функцией SleepEx: ноль в случае завершения по таймауту и Wait_IO_Completion в случае завершения из-за выполнения процедуры завершения (в последнем случае сначала выполняется процедура завершения, а потом только происходит возврат из функции SleepEx).

Существует также возможность ожидать выполнения процедуры завершения одновременно с ожиданием взведения событий с помощью функции WSAWaitForMultuipleEvents.

Если программа выполняет одновременно несколько операций перекрытого ввода-

вывода, встаёт вопрос, как при вызове процедуры завершения определить, какая из них

завершилась.

Для каждой такой операции должен быть создан уникальный экземпляр структуры WSAOverlapped

1. Можно сравнить указатель с теми, которые использовались для запуска операций перекрытого ввода-вывода, и определить, какая из них завершилась

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

3. Так как при использовании процедур завершения значение поля hEvent структуры WSAOverlapped игнорируется системой, программа может записать туда любое 32-битное значение и с его помощью определить, какая из операций завершена

При использовании процедур завершения допустимо использование функции WSAGetOverlappedResult для определения статуса операции, но её параметр fWait обязательно должен быть равен False, потому что события, необходимые для выполнения ожидания, не взводятся, и попытка дождаться окончания операции может привести к блокировке работы нити.

Соседние файлы в папке Программирование_распределенных_систем