//***** Описание на C++ *****
struct _WSAOVERLAPPED {
DWORD Internal;
DWORD InternalHigh;
DWORD Offset;
DWORD OffsetHigh;
WSAEVENT hEvent;
} WSAOVERLAPPED, *LPWSAOVEPLAPPED;
// ***** Описание на Delphi *****
PWSAOverlapped = ^TWSAOverlapped;
TWSAOverlapped = packed record
Internal, InternalHigh, Offer, OffsetHigh: DWORD;
hEvent: TWSAEvent;
end;
Поля Internal
, InternalHigh
, Offset
и OffsetHigh
предназначены для внутреннего использования системой, программа не должна выполнять никаких действий с ними. Поле hEvent
задает событие, которое будет взведено при завершении операции перекрытого ввода-вывода. Если на момент вызова функции WSARecv
данные в буфере сокета отсутствуют, она вернет значение SOCKET_ERROR
, а функция WSAGetLastError
— WSA_IO_PENDING
(997). Это значит, что операция начала выполняться в фоновом режиме. В этом случае функция WSARecv
не изменяет значения параметров NumberOfBytesRecvd
и Flag
. Поля структуры TWSAOverlapped
при этом также модифицируются, и эта структура должна быть сохранена программой в неприкосновенности до окончания операции перекрытого ввода-вывода. После окончания операции будет взведено событие, указанное в поле hEvent
параметра lpOverlapped
. При необходимости программа может дождаться этого взведения с помощью функции WSAWaitForMultipleEvents
.
Как только запрос будет выполнен, в буферах, переданных через параметр lpBuffers
, оказываются принятые данные. Но знания одного только факта, что запрос выполнен, недостаточно, чтобы этими данными воспользоваться, потому что, во-первых, неизвестен размер этих данных, а во-вторых, неизвестно, успешно ли завершена операция перекрытого ввода-вывода. Для получения недостающей информации служит функция WSAGetOverlappedResult
, прототип которой приведен в листинге 2.70.
WSAGetOverlappedResult
// ***** Описание на C++ *****
BOOL WSAGetOverlappedResult(SOCKET s, LPWSAOVERLAPРED lpOverlapped, LPDWORD lpcbTransfer, BOOL fWait, LPDWORD lpdwFlags);
// ***** Описание на Delphi *****
function WSAGetOverlappedResult(S: TSocket; lpOverlapped: PWSAOverlapped; var cbTransfer: DWORD; fWait: BOOL; var Flags: DWORD): BOOL;
Параметры S
и lpOverlapped
функции WSAGetOverlappedResult
определяют coкет и операцию перекрытого ввода-вывода, информацию о которой требуется получить. Их значения должны совпадать со значениями соответствующих параметров, переданных функции WSARecv
. Через параметр cbTransfer
возвращается число полученных байтов, а через параметр Flags
— флаги (напомним, что в случае TCP и UDP флаги не модифицируются, и выходное значение параметра Flags
будет равно входному значению параметра Flags
функции WSARecv
).
Допускается вызов функции WSAGetOverlappedResult
до того, как операция перекрытого ввода-вывода будет завершена. В этом случае поведение функции зависит от параметра fWait
. Если он равен True
, функция переводит нить в состояние ожидания до тех пор, пока операция не будет завершена. Если он равен False
, функция завершается немедленно с ошибкой WSA_IO_INCOMPLETE
(996).
Функция WSAGetOverlappedResult
возвращает True
, если операция перекрытого ввода-вывода успешно завершена, и False
, если произошли какие-то ошибки. Ошибка может возникнуть в одном из трех случаев:
1. Операция перекрытого ввода-вывода еще не завершена, а параметр fWait
равен False
.
2. Операция перекрытого ввода-вывода завершилась с ошибкой (например, из-за разрыва связи).
3. Параметры, переданные функции WSAGetOverlappedResult
, имеют некорректные значения.
Точную причину, по которой функция вернула False
, можно установить стандартным образом — по коду ошибки, возвращаемому функцией WSAGetLastError
.