Поделиться через


Функция обратного вызова LPWSPRECV (ws2spi.h)

Функция LPWSPRecv получает данные в сокете.

Синтаксис

LPWSPRECV Lpwsprecv;

int Lpwsprecv(
  [in]         SOCKET s,
  \[in\, out\] LPWSABUF lpBuffers,
  [in]         DWORD dwBufferCount,
  [out]        LPDWORD lpNumberOfBytesRecvd,
  \[in\, out\] LPDWORD lpFlags,
  [in]         LPWSAOVERLAPPED lpOverlapped,
  [in]         LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine,
  [in]         LPWSATHREADID lpThreadId,
  [out]        LPINT lpErrno
)
{...}

Параметры

[in] s

Дескриптор, определяющий подключенный сокет.

\\[in\\, out\\] lpBuffers

Указатель на массив структур WSABUF . Каждая структура WSABUF содержит указатель на буфер и длину буфера в байтах.

[in] dwBufferCount

Количество структур WSABUF в массиве lpBuffers .

[out] lpNumberOfBytesRecvd

Указатель на количество байтов, полученных этим вызовом.

\\[in\\, out\\] lpFlags

Указатель на флаги, указывающие способ выполнения вызова.

[in] lpOverlapped

Указатель на структуру WSAOverlapped (игнорируется для неперекрывающихся структур).

[in] lpCompletionRoutine

Тип: _In_opt_ LPWSAOVERLAPPED_COMPLETION_ROUTINE

Указатель на подпрограмму завершения, вызываемую при завершении операции получения (игнорируется для неперекрывающихся структур).

[in] lpThreadId

Указатель на структуру WSATHREADID , которая будет использоваться поставщиком в последующем вызове WPUQueueApc. Поставщик должен хранить указанную структуру WSATHREADID (не указатель на нее), пока не будет возвращена функция WPUQueueApc .

[out] lpErrno

Указатель на код ошибки.

Возвращаемое значение

Если ошибка не возникает и операция получения завершена немедленно, функция LPWSPRecv возвращает ноль. Обратите внимание, что в этом случае подпрограмма завершения, если она указана, уже будет помещена в очередь. В противном случае возвращается значение SOCKET_ERROR, а в lpErrno доступен определенный код ошибки. Код ошибки WSA_IO_PENDING указывает, что перекрывающаяся операция была успешно инициирована и что завершение будет указано позже. Любой другой код ошибки указывает на то, что перекрывающиеся операции не были инициированы и не будут указывать на завершение.

Код ошибки Значение
WSAENETDOWN
Произошел сбой сетевой подсистемы.
WSAENOTCONN
Сокет не подключен.
WSAEINTR
(Блокирующий) вызов был отменен через LPWSPCancelBlockingCall.
WSAEINPROGRESS
Выполняется блокировка вызова Windows Sockets или поставщик услуг по-прежнему обрабатывает функцию обратного вызова.
WSAENETRESET
Подключение было разорвано из-за действия поддержания активности, обнаруживающего сбой во время выполнения операции.
WSAEFAULT
Параметр lpBuffers не полностью содержится в допустимой части адресного пространства пользователя.
WSAENOTSOCK
Дескриптор не является сокетом.
WSAEOPNOTSUPP
MSG_OOB указано, но сокет не является типом потока, например тип SOCK_STREAM, данные OOB не поддерживаются в домене связи, связанном с этим сокетом, или сокет является однонаправленным и поддерживает только операции отправки.
WSAESHUTDOWN
Сокет был выключен; Невозможно получить через LPWSPRecv в сокете после вызова LPWSPShutdownс параметром SD_RECEIVE или SD_BOTH.
WSAEWOULDBLOCK
Windows NT. Перекрывающиеся сокеты: слишком много невыполненных перекрывающихся запросов ввода-вывода. Неперекрывающиеся сокеты. Сокет помечается как неблокируемый, и операция получения не может быть завершена немедленно.
WSAEMSGSIZE
Сообщение было слишком большим, чтобы поместиться в указанный буфер, и (только для ненадежных протоколов) все конечные части сообщения, которые не помещались в буфер, были удалены.
WSAEINVAL
Сокет не был привязан (например, с помощью LPWSPBind) или сокет не создан с перекрывающимся флагом.
WSAECONNABORTED
Виртуальный канал был прерван из-за истечения времени ожидания или другого сбоя.
WSAECONNRESET
Виртуальная цепь была сброшена удаленной стороной.
WSAEDISCON
Сокеты ориентированы на сообщения, и виртуальный канал был корректно закрыт удаленной стороной.
WSA_IO_PENDING
Перекрываемая операция была успешно инициирована, и ее завершение будет указано позже.
WSA_OPERATION_ABORTED
Операция перекрытия была отменена из-за закрытия сокета.

Комментарии

LPWSPRecv используется для подключенных сокетов или связанных сокетов без подключения, указанных параметром s , и используется для чтения входящих данных. Локальный адрес сокета должен быть известен. Это можно сделать явным образом через LPWSPBind или неявно через LPWSPAccept, LPWSPConnect, LPWSPSendTo или LPWSPJoinLeaf.

Для подключенных сокетов без подключения эта функция ограничивает адреса, с которых принимаются сообщения. Функция возвращает сообщения только с удаленного адреса, указанного в соединении. Сообщения с других адресов (автоматически) удаляются.

Для перекрывающихся сокетов LPWSPRecv используется для отправки одного или нескольких буферов, в которые будут помещены входящие данные по мере их доступности, после чего происходит указание завершения, указанного клиентом SPI windows Sockets (вызов подпрограммы завершения или настройка объекта события). Если операция не завершается немедленно, окончательное состояние завершения извлекается с помощью процедуры завершения или LPWSPGetOverlappedResult.

Если и lpOverlapped , и lpCompletionRoutine имеют значение NULL, сокет в этой функции будет рассматриваться как неперекрывающийся сокет.

Для неперекрывающихся сокетов параметры lpOverlapped, lpCompletionRoutine и lpThreadId игнорируются. Все данные, уже полученные и буферизируемые транспортом, будут скопированы в предоставленные пользовательские буферы. В случае блокирующего сокета без данных, которые в настоящее время получены и буферизованы транспортом, вызов будет блокироваться до получения данных. Windows Sockets 2 не определяет какой-либо стандартный механизм блокировки времени ожидания для этой функции. Для протоколов, действующих в качестве протоколов байтового потока, стек пытается вернуть как можно больше данных с учетом предоставленного буферного пространства и объема полученных данных. Однако получения одного байта достаточно, чтобы разблокировать вызывающий объект. Нет никакой гарантии, что будет возвращено более одного байта. Для протоколов, действующих в качестве ориентированных на сообщения, для разблокировки вызывающего объекта требуется полное сообщение.

Указывает, действует ли протокол в качестве байтового потока, определяется параметром XP1_MESSAGE_ORIENTED и XP1_PSEUDO_STREAM в его структуре WSAPROTOCOL_INFO и параметром флага MSG_PARTIAL, передаваемого в эту функцию (для протоколов, которые ее поддерживают). Соответствующие сочетания приведены в следующей таблице (звездочка (*) указывает, что значение этого бита в данном случае не имеет значения).

XP1_MESSAGE_ORIENTED XP1_PSEUDO_STREAM MSG_PARTIAL Действует как
не задан * * Поток байтов
* set * Поток байтов
set не задан set Поток байтов
set не задан не задан с ориентацией на сообщения

Предоставленные буферы заполняются в том порядке, в котором они отображаются в массиве, на который указывает lpBuffers, и буферы упаковываются таким образом, что не создаются отверстия.

Массив структур WSABUF , на которые указывает параметр lpBuffers , является временным. Если эта операция завершается перекрывающимся образом, поставщик услуг обязан записать этот массив указателей на структуры WSABUF перед возвращением из этого вызова. Это позволяет клиентам SPI сокетов Windows создавать массивы WSABUF на основе стека.

Для сокетов в стиле потока байтов (например, тип SOCK_STREAM) входящие данные помещаются в буферы до тех пор, пока буферы не будут заполнены, подключение не будет закрыто или не будет исчерпано внутренне буферизированных данных. Независимо от того, заполняют ли входящие данные все буферы, для перекрывающихся сокетов указывается завершение. Для сокетов, ориентированных на сообщения (например, тип SOCK_DGRAM), входящее сообщение помещается в предоставленные буферы вплоть до общего размера предоставленных буферов, а для перекрывающихся сокетов происходит указание завершения. Если сообщение больше, чем предоставленные буферы, буферы заполняются первой частью сообщения. Если MSG_PARTIAL функция поддерживается поставщиком услуг, флаг MSG_PARTIAL устанавливается в lpFlags и последующие операции получения можно использовать для получения остальной части сообщения. Если MSG_PARTIAL не поддерживается, но протокол является надежным, LPWSPRecv создает ошибку WSAEMSGSIZE и последующую операцию получения с большим буфером можно использовать для получения всего сообщения. В противном случае (то есть протокол является ненадежным и не поддерживает MSG_PARTIAL) лишние данные теряются, а LPWSPRecv выдает ошибку WSAEMSGSIZE.

Для сокетов, ориентированных на подключение, LPWSPRecv может указывать на корректное завершение виртуального канала одним из двух способов, в зависимости от того, является ли сокет потоком байтов или ориентирован на сообщение. Для потоков байтов ноль прочитанных байтов означает корректное закрытие и что больше байты не будут прочитаны. Для сокетов, ориентированных на сообщения, где сообщение с нулевым байтом часто допускается, используется код ошибки возврата WSAEDISCON , указывающий на корректное закрытие. В любом случае код ошибки возврата WSAECONNRESET указывает на прерывание закрытия.

Параметр lpFlags можно использовать для влияния на поведение вызова функции за пределами параметров, указанных для связанного сокета. То есть семантика этой функции определяется параметрами сокета и параметром lpFlags . Последний создается с помощью побитового оператора OR с любым из следующих значений.

Значение Значение
MSG_PEEK Просматривает входящие данные. Данные копируются в буфер, но не удаляются из входной очереди. Этот флаг действителен только для неперекрывающихся сокетов.
MSG_OOB Обрабатывает данные вне диапазона (OOB).
MSG_PARTIAL Этот флаг предназначен только для сокетов, ориентированных на сообщения. В выходных данных указывает, что предоставленные данные являются частью сообщения, переданного отправителем. Остальные части сообщения будут предоставлены в последующих операциях получения. Последующая операция получения с снятыми флагами MSG_PARTIAL указывает на конец сообщения отправителя. В качестве входного параметра MSG_PARTIAL указывает, что операция получения должна завершиться, даже если поставщиком услуг была получена только часть сообщения.

Если перекрывающаяся операция завершается немедленно, LPWSPRecv возвращает нулевое значение, а параметр lpNumberOfBytesRecvd обновляется на количество полученных байтов, а биты флагов, указывающие параметром lpFlags , также обновляются. Если перекрывающаяся операция успешно инициирована и завершится позже, LPWSPRecv возвращает SOCKET_ERROR и указывает код ошибки WSA_IO_PENDING. В этом случае lpNumberOfBytesRecvd и lpFlags не обновляются. После завершения перекрываемой операции объем передаваемых данных указывается либо с помощью параметра cbTransferred в подпрограмме завершения (если он указан), либо с помощью параметра lpcbTransfer в LPWSPGetOverlappedResult. Значения флагов получаются либо с помощью параметра dwFlags подпрограммы завершения, либо путем проверки параметра lpdwFlagswSAGetOverlappedResult.

Поставщики должны разрешить вызов этой функции из процедуры завершения предыдущей функции LPWSPRecv, LPWSPRecvFrom, LPWSPSend или LPWSPSendTo . Однако для заданного сокета подпрограммы завершения ввода-вывода не могут быть вложенными. Это позволяет полностью выполнять передачу конфиденциальных во времени данных в контексте вытеснения.

Параметр lpOverlapped должен быть действителен в течение всего периода перекрываемой операции. Если одновременно выполняется несколько операций ввода-вывода, каждая из них должна ссылаться на отдельную перекрывающуюся структуру. Структура WSAOverlapped определяется на собственной справочной странице.

Если параметр lpCompletionRoutine имеет значение NULL, поставщик службы сообщает члену hEventобъекта lpOverlapped , когда перекрываемая операция завершается, если она содержит допустимый дескриптор объекта события. Клиент SPI windows Sockets может использовать LPWSPGetOverlappedResult для ожидания или опроса объекта события.

Если значение lpCompletionRoutine не равно NULL, элемент hEvent игнорируется и может использоваться клиентом SPI сокетов Windows для передачи контекстных сведений в подпрограмму завершения. Клиент, который передает значение NULL lpCompletionRoutine , а затем вызывает WSAGetOverlappedResult для того же перекрывающегося запроса ввода-вывода, может не задать для параметра fWait для этого вызова WSAGetOverlappedResult значение TRUE. В этом случае использование элемента hEvent не определено, и попытка ожидания элемента hEvent приведет к непредсказуемым результатам.

Поставщик услуг отвечает за организацию вызова указанной клиентом процедуры завершения после завершения перекрывающейся операции. Так как подпрограмма завершения должна выполняться в контексте того же потока, который инициировал перекрывающуюся операцию, ее нельзя вызвать непосредственно от поставщика услуг. Ws2_32.dll предлагает механизм асинхронного вызова процедур (APC) для упрощения вызова процедур завершения.

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

WPUQueueApc принимает в качестве входных параметров указатель на структуру WSATHREADID (предоставленную поставщику через входной параметр lpThreadId ), указатель на вызываемую функцию APC и значение контекста, которое затем передается в функцию APC. Так как доступно только одно значение контекста, сама функция APC не может быть указанной клиентом подпрограммой завершения. Поставщик услуг должен вместо этого предоставить указатель на собственную функцию APC, которая использует предоставленное значение контекста для доступа к необходимым сведениям о результатах для перекрываемой операции, а затем вызывает подпрограмму завершения, указанную клиентом.

Ниже приведен прототип процедуры завершения, предоставляемой клиентом.

void CALLBACK 
CompletionRoutine(  
  IN DWORD           dwError, 
  IN DWORD           cbTransferred, 
  IN LPWSAOVERLAPPED lpOverlapped, 
  IN DWORD           dwFlags 
);

Параметр CompletionRoutine является заполнителем для имени функции, предоставленной клиентом. dwError указывает состояние завершения для перекрываемой операции, как указано в lpOverlapped. Параметр cbTransferred указывает количество полученных байтов. DwFlags содержит сведения, которые появились бы в lpFlags , если бы операция получения была завершена немедленно. Эта функция не возвращает значение.

Процедуры завершения можно вызывать в любом порядке, но не обязательно в том же порядке, в котором выполняются перекрывающиеся операции. Однако размещенные буферы гарантированно заполняются в том же порядке, в котором они предоставляются.

Примечание

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

Требования

Требование Значение
Минимальная версия клиента сборка Windows 10 20348
Минимальная версия сервера сборка Windows 10 20348
Верхняя часть ws2spi.h

См. также раздел

WPUCloseEvent

WPUCreateEvent

WPUQueueApc

LPWSPGetOverlappedResult

LPWSPSocket