Функция обратного вызова LPWSPSENDTO (ws2spi.h)
Функция LPWSPSendTo отправляет данные в определенное место назначения с помощью перекрывающихся операций ввода-вывода.
Синтаксис
LPWSPSENDTO Lpwspsendto;
int Lpwspsendto(
[in] SOCKET s,
[in] LPWSABUF lpBuffers,
[in] DWORD dwBufferCount,
[out] LPDWORD lpNumberOfBytesSent,
[in] DWORD dwFlags,
[in] const sockaddr *lpTo,
[in] int iTolen,
[in] LPWSAOVERLAPPED lpOverlapped,
[in] LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine,
[in] LPWSATHREADID lpThreadId,
[out] LPINT lpErrno
)
{...}
Параметры
[in] s
Дескриптор, определяющий сокет.
[in] lpBuffers
Указатель на массив структур WSABUF . Каждая структура WSABUF содержит указатель на буфер и длину буфера в байтах. Для приложения Winsock после вызова функции LPWSPSendTo система владеет этими буферами, и приложение может не получить к ним доступ. Буферы данных, на которые ссылается каждая структура WSABUF, принадлежат системе, и приложение может не обращаться к ним в течение всего времени существования вызова.
[in] dwBufferCount
Количество структур WSABUF в массиве lpBuffers .
[out] lpNumberOfBytesSent
Указатель на количество байтов, отправленных этим вызовом.
[in] dwFlags
Набор флагов, указывающий способ, с помощью которого выполняется вызов.
[in] lpTo
Необязательный указатель на адрес целевого сокета в структуре sockaddr .
[in] iTolen
Размер (в байтах) адреса, на который указывает параметр lpTo .
[in] lpOverlapped
Указатель на структуру WSAOverlapped (игнорируется для неперекрывающихся сокетов).
[in] lpCompletionRoutine
Тип: _In_opt_ LPWSAOVERLAPPED_COMPLETION_ROUTINE
Указатель на подпрограмму завершения, вызываемую при завершении операции отправки (игнорируется для неперекрывающихся сокетов).
[in] lpThreadId
Указатель на структуру WSATHREADID , которая будет использоваться поставщиком в последующем вызове WPUQueueApc. Поставщик должен хранить указанную структуру WSATHREADID (не указатель на нее), пока не будет возвращена функция WPUQueueApc .
[out] lpErrno
Указатель на код ошибки.
Возвращаемое значение
Если ошибка не возникает и операция получения завершена немедленно, функция LPWSPSendTo возвращает ноль. Обратите внимание, что в этом случае подпрограмма завершения, если она указана, уже будет помещена в очередь. В противном случае возвращается значение SOCKET_ERROR, а в lpErrno доступен определенный код ошибки. Код ошибки WSA_IO_PENDING указывает, что перекрывающаяся операция была успешно инициирована и что завершение будет указано позже. Любой другой код ошибки указывает, что не была инициирована перекрывающаяся операция и не будет никаких указаний завершения.
Код ошибки | Значение |
---|---|
Произошел сбой сетевой подсистемы. | |
Запрошенный адрес является широковещательным адресом, но соответствующий флаг не установлен. | |
(Блокирующий) вызов был отменен через LPWSPCancelBlockingCall. | |
Выполняется блокировка вызова Windows Sockets или поставщик услуг по-прежнему обрабатывает функцию обратного вызова. | |
Параметры lpBuffers или lpTo не являются частью адресного пространства пользователя или параметр lpTo слишком мал. | |
Подключение было разорвано из-за действия поддержания активности, обнаруживающего сбой во время выполнения операции. | |
Поставщик сокетов Windows сообщает о взаимоблокировке буфера. | |
Сокет не подключен (только сокеты, ориентированные на подключение). | |
Дескриптор не является сокетом. | |
MSG_OOB указано, но сокет не является потоковым, например тип SOCK_STREAM, данные OOB не поддерживаются в домене связи, связанном с этим сокетом, MSG_PARTIAL не поддерживаются, либо сокет является однонаправленным и поддерживает только операции получения. | |
Сокет был выключен; невозможно использовать LPWSPSendTo в сокете после вызова LPWSPShutdownс параметром SD_SEND или SD_BOTH. | |
Windows NT: перекрывающиеся сокеты: слишком много невыполненных перекрывающихся запросов ввода-вывода. Неперекрывающиеся сокеты. Сокет помечается как неблокируемый, и операция отправки не может быть завершена немедленно. | |
Сокет ориентирован на сообщения, и сообщение больше максимального значения, поддерживаемого базовым транспортом. | |
Сокет не привязан к LPWSPBind или сокет не создан с флагом перекрытия. | |
Виртуальный канал был прерван из-за истечения времени ожидания или другого сбоя. | |
Виртуальная цепь была сброшена удаленной стороной. | |
Удаленный адрес не является допустимым адресом (например, ADDR_ANY). | |
Адреса из заданного семейства адресов не могут использоваться с этим сокетом. | |
Требуется адрес назначения. | |
В настоящее время сеть недоступна с этого узла. | |
Перекрывающиеся операции были отменены из-за закрытия сокета или выполнения команды SIO_FLUSH в LPWSPIoctl. |
Комментарии
Функция LPWSPSendTo обычно используется в сокете без подключения, заданном параметром s , для отправки датаграммы, содержащейся в одном или нескольких буферах, в определенный одноранговый сокет, определенный параметром lpTo . Даже если сокет без подключения ранее был подключен к определенному адресу с помощью функции LPWSPConnect , lpTo переопределяет адрес назначения только для этой датаграммы. В сокете, ориентированном на подключение, параметры lpTo и iToLen игнорируются; в этом случае функция LPWSPSendTo эквивалентна LPWSPSend.
Для перекрывающихся сокетов (созданных с помощью LPWSPSocket с флагом WSA_FLAG_OVERLAPPED) это будет происходить с помощью перекрывающихся операций ввода-вывода, если только lpOverlapped и lpCompletionRoutine не имеют значения NULL , в этом случае сокет считается неперекрытым сокетом. Указание завершения (вызов подпрограммы завершения или настройка объекта события) будет происходить, когда предоставленные буферы были использованы транспортом. Если операция не завершается немедленно, окончательное состояние завершения извлекается с помощью процедуры завершения или LPWSPGetOverlappedResult.
Для неперекрывающихся сокетов параметры lpOverlapped, lpCompletionRoutine и lpThreadId игнорируются, а LPWSPSendTo принимает обычную синхронную семантику. Данные копируются из предоставленных буферов в буфер транспорта. Если сокет не блокируется и ориентирован на поток, а в буфере транспорта недостаточно места, LPWSPSendTo возвращает только часть буферов клиента SPI сокетов Windows. Учитывая ту же ситуацию с буфером и блокирующим сокетом, LPWSPSendTo будет блокироваться до тех пор, пока не будет занято все содержимое буфера клиента SPI сокетов Windows.
Массив структур WSABUF , на которые указывает параметр lpBuffers , является временным. Если эта операция завершается перекрывающимся образом, поставщик услуг обязан захватить эти структуры WSABUF перед возвращением из этого вызова. Это позволяет приложениям создавать массивы WSABUF на основе стека.
Для сокетов, ориентированных на сообщения, необходимо соблюдать осторожность, чтобы не превышать максимальный размер сообщения базового транспорта, который можно получить, получив значение параметра сокета SO_MAX_MSG_SIZE. Если данные слишком длинные для атомарной передачи через базовый протокол, возвращается ошибка WSAEMSGSIZE и данные не передаются.
Обратите внимание, что успешное завершение LPWSPSendTo не означает, что данные были успешно доставлены.
Параметр iFlags можно использовать для влияния на поведение вызова функции за пределами параметров, указанных для связанного сокета. То есть семантика этой функции определяется параметрами сокета и параметром dwFlags . Последний создается с помощью побитового оператора OR с любым из следующих значений.
Значение | Значение |
---|---|
MSG_DONTROUTE | Указывает, что данные не должны подвергаться маршрутизации. Поставщик службы Windows Sockets может игнорировать этот флаг. |
MSG_OOB | Отправляет данные OOB (только сокет в стиле потока, например SOCK_STREAM). |
MSG_PARTIAL | Указывает, что lpBuffers содержит только частичное сообщение. Обратите внимание, что код ошибки WSAEOPNOTSUPP будет возвращен транспортами, которые не поддерживают частичную передачу сообщений. |
Если перекрывающаяся операция завершается немедленно, LPWSPSendTo возвращает нулевое значение, а параметр lpNumberOfBytesSent обновляется числом отправленных байтов. Если перекрывающаяся операция успешно инициирована и завершится позже, LPWSPSendTo возвращает SOCKET_ERROR и указывает код ошибки WSA_IO_PENDING. В этом случае lpNumberOfBytesSent не обновляется. После завершения перекрываемой операции объем передаваемых данных указывается либо с помощью параметра cbTransferred в подпрограмме завершения (если он указан), либо с помощью параметра lpcbTransfer в LPWSPGetOverlappedResult.
Поставщики должны разрешить вызов этой функции из процедуры завершения предыдущей функции LPWSPRecv, LPWSPRecvFrom, LPWSPSend или LPWSPSendTo . Однако для заданного сокета подпрограммы завершения ввода-вывода не могут быть вложенными. Это позволяет полностью выполнять передачу конфиденциальных во времени данных в контексте вытеснения.
Параметр lpOverlapped должен быть действителен в течение всего периода перекрываемой операции. Если одновременно выполняется несколько операций ввода-вывода, каждая из них должна ссылаться на отдельную перекрывающуюся структуру. Структура WSAOverlapped определяется на собственной справочной странице.
Если параметр lpCompletionRoutine имеет значение NULL, поставщик службы сообщает члену hEventобъекта lpOverlapped , когда перекрываемая операция завершается, если она содержит допустимый дескриптор объекта события. Клиенты SPI сокетов Windows могут использовать LPWSPGetOverlappedResult для ожидания или опроса объекта события.
Если значение lpCompletionRoutine не равно NULL, элемент hEvent игнорируется и может использоваться клиентом SPI сокетов Windows для передачи контекстных сведений в подпрограмму завершения. Клиент, который передает lpCompletionRoutine, отличный от NULL, а затем вызывает 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 будет равно нулю. Эта функция не возвращает значение.
Подпрограммы завершения можно вызывать в любом порядке, хотя и не обязательно в том же порядке, в каком выполняются перекрывающиеся операции. Однако поставщик услуг гарантирует клиенту, что отправленные буферы отправляются в том же порядке, в который они предоставляются.
Примечание
Все операции ввода-вывода, инициированные данным потоком, отменяются при выходе из этого потока. Для перекрывающихся сокетов ожидающие асинхронные операции могут завершиться ошибкой, если поток будет закрыт до завершения операций. Дополнительные сведения см. в разделе ExitThread .
Требования
Минимальная версия клиента | Windows 2000 Professional [только классические приложения] |
Минимальная версия сервера | Windows 2000 Server [только классические приложения] |
Верхняя часть | ws2spi.h |