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


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

Функция LPWSPSend отправляет данные в подключенный сокет.

Синтаксис

LPWSPSEND Lpwspsend;

int Lpwspsend(
  [in]  SOCKET s,
  [in]  LPWSABUF lpBuffers,
  [in]  DWORD dwBufferCount,
  [out] LPDWORD lpNumberOfBytesSent,
  [in]  DWORD dwFlags,
  [in]  LPWSAOVERLAPPED lpOverlapped,
  [in]  LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine,
  [in]  LPWSATHREADID lpThreadId,
  [out] LPINT lpErrno
)
{...}

Параметры

[in] s

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

[in] lpBuffers

Указатель на массив структур WSABUF . Каждая структура WSABUF содержит указатель на буфер и длину буфера в байтах. Для приложения Winsock после вызова функции LPWSPSend система владеет этими буферами, и приложение может не получить к ним доступ. Буферы данных, на которые ссылается каждая структура WSABUF, принадлежат системе, и приложение может не обращаться к ним в течение всего времени существования вызова.

[in] dwBufferCount

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

[out] lpNumberOfBytesSent

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

[in] dwFlags

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

[in] lpOverlapped

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

[in] lpCompletionRoutine

Тип: _In_opt_ LPWSAOVERLAPPED_COMPLETION_ROUTINE

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

[in] lpThreadId

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

[out] lpErrno

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

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

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

Код ошибки Значение
WSAENETDOWN
Произошел сбой сетевой подсистемы.
WSAEACCES
Запрошенный адрес является широковещательным адресом, но соответствующий флаг не установлен.
WSAEINPROGRESS
Выполняется блокировка вызова Windows Sockets или поставщик услуг по-прежнему обрабатывает функцию обратного вызова.
WSAEFAULT
Параметр lpBuffers не полностью содержится в допустимой части адресного пространства пользователя.
WSAENETRESET
Подключение было разорвано из-за сброса удаленного узла.
WSAENOBUFS
Подключение было разорвано из-за действия поддержания активности, обнаруживающего сбой во время выполнения операции.
WSAENOTCONN
Сокет не подключен.
WSAENOTSOCK
Дескриптор не является сокетом.
WSAEOPNOTSUPP
MSG_OOB указано, но сокет не является потоковым, например тип SOCK_STREAM, данные OOB не поддерживаются в домене связи, связанном с этим сокетом, MSG_PARTIAL не поддерживаются, либо сокет является однонаправленным и поддерживает только операции получения.
WSAESHUTDOWN
Сокет был выключен; Невозможно выполнить LPWSPSend в сокете после вызова LPWSPShutdown с параметром SD_SEND или SD_BOTH.
WSAEWOULDBLOCK
**Windows NT:** Перекрывающиеся сокеты: слишком много невыполненных перекрывающихся запросов ввода-вывода. Неперекрывающиеся сокеты. Сокет помечается как неблокируемый, и операция отправки не может быть завершена немедленно.
WSAEMSGSIZE
Сокет ориентирован на сообщения, и сообщение больше максимального значения, поддерживаемого базовым транспортом.
WSAEINVAL
Сокет не привязан к LPWSPBind или сокет не создан с флагом перекрытия.
WSAECONNABORTED
Виртуальный канал был прерван из-за истечения времени ожидания или другого сбоя.
WSAECONNRESET
Виртуальная цепь была сброшена удаленной стороной.
WSA_OPERATION_ABORTED
Перекрывающиеся операции были отменены из-за закрытия сокета или выполнения команды SIO_FLUSH в LPWSPIoctl.

Комментарии

Функция LPWSPSend используется для записи исходящих данных из одного или нескольких буферов в сокете, ориентированном на подключение, указанном в параметре s. Однако его также можно использовать для сокетов без подключения, которые имеют указанный адрес однорангового узла по умолчанию, установленный с помощью функции LPWSPConnect .

Для перекрывающихся сокетов (созданных с помощью LPWSPSocket с флагом WSA_FLAG_OVERLAPPED) это будет происходить с помощью перекрывающихся операций ввода-вывода, если только lpOverlapped и lpCompletionRoutine не имеют значения NULL, в этом случае сокет считается неперекрытым сокетом. Указание завершения (вызов подпрограммы завершения или настройка объекта события) будет происходить, когда предоставленные буферы были использованы транспортом. Если операция не завершается немедленно, окончательное состояние завершения извлекается с помощью процедуры завершения или LPWSPGetOverlappedResult.

Для неперекрывающихся сокетов параметры lpOverlapped, lpCompletionRoutine и lpThreadId игнорируются, а LPWSPSend принимает обычную синхронную семантику. Данные копируются из предоставленных буферов в буфер транспорта. Если сокет не блокируется и ориентирован на поток, а в буфере транспорта недостаточно места, LPWSPSend возвращает только часть предоставленных буферов. Учитывая ту же ситуацию с буфером и блокирующий сокет, LPWSPSend будет блокироваться до тех пор, пока не будет занято все предоставленное содержимое буфера.

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

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

Обратите внимание, что успешное завершение LPWSPSend не означает, что данные были успешно доставлены.

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

Значение Значение
MSG_DONTROUTE Указывает, что данные не должны подвергаться маршрутизации. Поставщик службы Windows Sockets может игнорировать этот флаг;
MSG_OOB Отправляет данные OOB (только сокет в стиле потока, например SOCK_STREAM).
MSG_PARTIAL Указывает, что lpBuffers содержит только частичное сообщение. Обратите внимание, что код ошибки WSAEOPNOTSUPP будет возвращен для сообщений, которые не поддерживают частичные передачи сообщений.

 

 

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

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

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

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

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

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

Поставщик услуг упорядочивает выполнение функции в правильном потоке путем вызова WPUQueueApc. Обратите внимание, что эта функция должна вызываться в контексте того же процесса (но не обязательно того же потока), который использовался для запуска перекрывающейся операции. Поставщик услуг отвечает за то, чтобы этот контекст процесса был активным перед вызовом 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

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

WPUQueueApc

LPWSPGetOverlappedResult

LPWSPSocket