функция обратного вызова LPFN_WSARECVMSG (mswsock.h)

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

Функция обратного вызова WSARecvMsg получает дополнительные данные или сведения об управлении с сообщением из подключенных и неподключенных сокетов.

Примечание

Эта функция является расширением майкрософт для спецификации Сокетов Windows.

Синтаксис

LPFN_WSARECVMSG LpfnWsarecvmsg;

INT LpfnWsarecvmsg(
  SOCKET s,
  LPWSAMSG lpMsg,
  LPDWORD lpdwNumberOfBytesRecvd,
  LPWSAOVERLAPPED lpOverlapped,
  LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine
)
{...}

Параметры

s

Тип: _In_ SOCKET

Дескриптор, идентифицирующий сокет.

lpMsg

Тип: _Inout_ LPWSAMSG

Указатель на структуру WSAMSG на основе спецификации Posix.1g для структуры msghdr.

lpdwNumberOfBytesRecvd

Тип: _Out_opt_ LPDWORD

Указатель на DWORD , содержащий количество байтов, полученных этим вызовом, если операция WSARecvMsg завершается немедленно.

Чтобы избежать потенциально ошибочных результатов, передайте значение NULL для этого параметра, если параметр lpOverlapped не имеет значение NULL . Этот параметр может иметь значение NULL , только если параметр lpOverlapped не равен NULL.

lpOverlapped

Тип: _Inout_opt_ LPWSAOVERLAPPED

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

lpCompletionRoutine

Тип: _In_opt_ LPWSAOVERLAPPED_COMPLETION_ROUTINE

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

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

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

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

Код ошибки Значение
WSAECONNRESET

Для сокета датаграмм UDP эта ошибка указывает на то, что предыдущая операция отправки привела к сообщению ICMP "Порт недоступен".

WSAEFAULT

Параметр lpBuffers, lpFlags, lpFrom, lpNumberOfBytesRecvd, lpFromlen, lpOverlapped или lpCompletionRoutine не полностью содержится в допустимой части адресного пространства пользователя: буфер lpFrom был слишком мал для размещения однорангового адреса. Эта ошибка также возвращается, если элемент имени структуры WSAMSG , на который указывает параметр lpMsg , был указателем NULL и элемент namelen структуры WSAMSG не был равен нулю. Эта ошибка также возвращается, если элемент Control.buf структуры WSAMSG , на который указывает параметр lpMsg , был указателем NULL , а элемент Control.len структуры WSAMSG не был равен нулю.

WSAEINPROGRESS

Выполняется блокирующий вызов Windows Sockets 1.1 или поставщик услуг по-прежнему обрабатывает функцию обратного вызова.

WSAEINTR

Блокирующий вызов сокета Windows 1.1 был отменен через WSACancelBlockingCall.

WSAEINVAL

Сокет не был привязан (например, с привязкой).

WSAEMSGSIZE

Сообщение было слишком большим, чтобы поместиться в указанный буфер, и (только для ненадежных протоколов) все конечные части сообщения, которые не помещались в буфер, были удалены.

WSAENETDOWN

Произошел сбой сетевой подсистемы.

WSAENETRESET

Для сокета датаграмм эта ошибка указывает на то, что срок жизни истек.

WSAENOTCONN

Сокет не подключен (только сокеты, ориентированные на подключение).

WSAETIMEDOUT

Время ожидания сокета истекло. Эта ошибка возвращается, если для сокета задано время ожидания с помощью параметра сокета SO_RCVTIMEO и превышено время ожидания.

WSAEOPNOTSUPP

Операция сокета не поддерживается. Эта ошибка возвращается, если элемент dwFlags структуры WSAMSG , на который указывает параметр lpMsg , содержит флаг элемента управления MSG_PEEK в сокете, отличном от datagram.

WSAEWOULDBLOCK

Windows NT:

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

WSANOTINITIALISED

Перед использованием этой функции должен быть выполнен успешный вызов WSAStartup .

WSA_IO_PENDING

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

WSA_OPERATION_ABORTED

Перекрываемая операция была отменена из-за закрытия сокета.

Комментарии

Функцию WSARecvMsg можно использовать вместо функций WSARecv и WSARecvFrom для получения данных и дополнительных сведений об управлении из подключенных и неподключенных сокетов. Функцию WSARecvMsg можно использовать только с датаграммами и необработанными сокетами. Дескриптор сокета в параметре s должен быть открыт с типом сокета SOCK_DGRAM или SOCK_RAW.

Примечание Указатель функции для функции WSARecvMsg должен быть получен во время выполнения путем вызова функции WSAIoctl с указанным SIO_GET_EXTENSION_FUNCTION_POINTER кодом операции. Входной буфер, передаваемый в функцию WSAIoctl , должен содержать WSAID_WSARECVMSG, глобальный уникальный идентификатор (GUID), значение которого определяет функцию расширения WSARecvMsg . При успешном выполнении выходные данные, возвращаемые функцией WSAIoctl , содержат указатель на функцию WSARecvMsg . Guid WSAID_WSARECVMSG определяется в файле заголовка Mswsock.h .

 

Элемент dwFlags структуры WSAMSG , на который указывает параметр lpMsg , может содержать только флаг элемента управления MSG_PEEK для входных данных.

Перекрывающиеся сокеты создаются с помощью вызова функции WSASocket с установленным флагом WSA_FLAG_OVERLAPPED . Для перекрывающихся сокетов при получении сведений используется перекрывающийся ввод-вывод, если только параметры lpOverlapped и lpCompletionRoutine не имеют значения NULL. Сокет рассматривается как неперекрытый сокет, если параметры lpOverlapped и lpCompletionRoutine имеют значение NULL.

Указание завершения происходит с перекрывающимися сокетами. После использования буфера или буферов транспортом активируется подпрограмма завершения или устанавливается объект события. Если операция не завершается немедленно, окончательное состояние завершения извлекается с помощью процедуры завершения или путем вызова функции WSAGetOverlappedResult .

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

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

Примечание Параметр сокета SO_RCVTIMEO применяется только к блокирующим сокетам.

 

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

Если эта функция выполняется перекрывающимся образом, поставщик услуг Winsock обязан захватить эту структуру WSABUF перед возвращением из этого вызова. Это позволяет приложениям создавать массивы WSABUF на основе стека, на которые указывает член lpBuffers структуры WSAMSG , на которую указывает параметр lpMsg .

Для сокетов, ориентированных на сообщения (тип сокета SOCK_DGRAM или SOCK_RAW), входящее сообщение помещается в буферы вплоть до общего размера буферов, а для перекрывающихся сокетов появляется указание завершения. Если сообщение больше буферов, буферы заполняются первой частью сообщения и лишние данные теряются, а WSARecvMsg создает ошибку WSAEMSGSIZE.

Если параметр сокета IP_PKTINFO включен для сокета IPv4 типа SOCK_DGRAM или SOCK_RAW, функция WSARecvMsg возвращает сведения о пакете в структуре WSAMSG , на которую указывает параметр lpMsg . Один из объектов данных управления в возвращаемой структуре WSAMSG будет содержать in_pktinfo структуру, используемую для хранения сведений об адресе полученного пакета.

Для датаграмм, полученных по протоколу IPv4, элемент Control полученной структуры WSAMSG будет содержать структуру WSABUF , содержащую структуру WSACMSGHDR . Элемент cmsg_level этой структуры WSACMSGHDR будет содержать IPPROTO_IP, элемент cmsg_type этой структуры будет содержать IP_PKTINFO, а элемент cmsg_data будет содержать in_pktinfo структуру, используемую для хранения сведений об адресе полученного пакета IPv4. IPv4-адрес в структуре in_pktinfo — это IPv4-адрес, с которого был получен пакет.

Если параметр сокета IPV6_PKTINFO включен для сокета IPv6 типа SOCK_DGRAM или SOCK_RAW, функция WSARecvMsg возвращает сведения о пакете в структуре WSAMSG , на которую указывает параметр lpMsg . Один из объектов контрольных данных в возвращаемой структуре WSAMSG будет содержать in6_pktinfo структуру, используемую для хранения сведений об адресе полученного пакета.

Для датаграмм, полученных по протоколу IPv6, элемент Control полученной структуры WSAMSG будет содержать структуру WSABUF , содержащую структуру WSACMSGHDR . Элемент cmsg_level этой структуры WSACMSGHDR будет содержать IPPROTO_IPV6, элемент cmsg_type этой структуры будет содержать IPV6_PKTINFO, а элемент cmsg_data будет содержать in6_pktinfo структуру, используемую для хранения сведений об адресах полученных пакетов IPv6. IPv6-адрес в структуре in6_pktinfo — это IPv6-адрес, с которого был получен пакет.

Если для сокета datagram с двумя стеками приложение требует, чтобы функция WSARecvMsg возвращала сведения о пакете в структуре WSAMSG для датаграмм, полученных по протоколу IPv4, то параметр сокета IP_PKTINFO должен иметь значение true в сокете. Если в сокете задано значение true только для параметра IPV6_PKTINFO , сведения о пакетах будут предоставляться для датаграмм, полученных по протоколу IPv6, но могут не предоставляться для датаграмм, полученных по протоколу IPv4.

Обратите внимание, что файл заголовка Ws2ipdef.h автоматически включается в Ws2tcpip.h и никогда не должен использоваться напрямую.

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

 

Windows Phone 8. Эта функция поддерживается для приложений Магазина Windows Phone Windows Phone 8 и более поздних версий.

Windows 8.1 и Windows Server 2012 R2. Эта функция поддерживается для приложений Магазина Windows в Windows 8.1, Windows Server 2012 R2 и более поздних версий.

dwFlags

На входных данных член dwFlags структуры WSAMSG , на который указывает параметр lpMsg , можно использовать для влияния на поведение вызова функции за пределами параметров сокета, указанных для связанного сокета. То есть семантика этой функции определяется параметрами сокета и членом dwFlags структуры WSAMSG . Единственным возможным входным значением для члена dwFlags структуры WSAMSG , на которую указывает параметр lpMsg , является MSG_PEEK.

Значение Значение
MSG_PEEK Обзор на входящие данные. Данные копируются в буфер, но не удаляются из очереди ввода. Этот флаг действителен только для неперекрывающихся сокетов.

 

Возможные значения для элемента dwFlags во входных данных определяются в файле заголовка Winsock2.h .

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

Значение Значение
MSG_BCAST Датаграмма была получена в виде трансляции на уровне ссылок или с IP-адресом назначения, который является широковещательным адресом.
MSG_CTRUNC Контрольные (вспомогательные) данные были усечены. Было больше контрольных данных, чем в выделенном для процесса помещении.
MSG_MCAST Датаграмма получена с IP-адресом назначения, который является адресом многоадресной рассылки.
MSG_TRUNC Датаграмма была усечена. Было больше данных, чем в выделенном для процесса помещении.

 

В microsoft пакет средств разработки программного обеспечения для Windows (SDK), выпущенном для Windows Vista и более поздних версий, организация файлов заголовков изменилась, а возможные значения для члена dwFlags в выходных данных определяются в файле заголовка Ws2def.h, который автоматически включается в файл заголовка Winsock2.h.

В версиях пакета SDK для Windows Server 2003 и более ранних версий возможные значения элемента dwFlags в выходных данных определяются в файле заголовка Mswsock.h .

Примечание При выполнении блокирующего вызова Winsock, например WSARecvMsg , с параметром lpOverlapped , имеющим значение NULL, Winsock может потребоваться дождаться сетевого события, прежде чем вызов сможет завершиться. В этой ситуации Winsock выполняет оповещенное ожидание, которое может быть прервано асинхронным вызовом процедуры (APC), запланированным в том же потоке. Выполнение другого блокирующего вызова Winsock внутри APC, который прервал текущий блокирующий вызов Winsock в том же потоке, приведет к неопределенному поведению и никогда не должен выполняться клиентами Winsock.

 

Перекрывающиеся ввода-вывода сокета

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

Функция WSARecvMsg с перекрывающимся вводом-выводом может быть вызвана из подпрограммы завершения предыдущей функции WSARecv, WSARecvFrom, WSARecvMsg, WSASendMsg или WSASendTo. Для заданного сокета подпрограммы завершения ввода-вывода не будут вложенными. Это позволяет передавать конфиденциальные данные во времени полностью в контексте вытеснения.

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

Если параметр lpCompletionRoutine имеет значение NULL, параметр hEventlpOverlapped получает сигнал о завершении перекрывающейся операции, если он содержит допустимый дескриптор объекта события. Приложение может использовать WSAWaitForMultipleEvents или WSAGetOverlappedResult для ожидания или опроса объекта события.

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

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

Ниже приведен прототип процедуры завершения.


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

CompletionRoutine — это заполнитель для имени функции, определяемой приложением или библиотекой. Параметр dwError указывает состояние завершения перекрывающейся операции, как указано в параметре lpOverlapped . Параметр cbTransferred указывает количество полученных байтов. Параметр dwFlags содержит сведения, которые также возвращаются в элементе dwFlags структуры WSAMSG , на которую указывает параметр lpMsg , если операция получения была завершена немедленно. Функция CompletionRoutine не возвращает значение.

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

Если вы используете порты завершения ввода-вывода, имейте в виду, что порядок вызовов WSARecvMsg также является порядком заполнения буферов. Функция WSARecvMsg не должна вызываться в одном сокете одновременно из разных потоков, так как это может привести к непредсказуемому буферному порядку.

Требования

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

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

ExitThread

IP_PKTINFO

IPV6_PKTINFO

Справочник по Winsock

Функции Winsock

WSABUF

WSAGetLastError

WSAIoctl

WSAMSG

WSAOVERLAPPED

WSARecv

WSARecvFrom

WSASend

WSASendMsg

WSASendTo

WSAStartup

WSAWaitForMultipleEvents