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

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

Примечание Эта функция является расширением для спецификации сокетов Windows, относящаяся к корпорации Майкрософт.

 

Синтаксис

LPFN_CONNECTEX LpfnConnectex;

BOOL LpfnConnectex(
  [in]           SOCKET s,
  [in]           const sockaddr *name,
  [in]           int namelen,
  [in, optional] PVOID lpSendBuffer,
  [in]           DWORD dwSendDataLength,
  [out]          LPDWORD lpdwBytesSent,
  [in]           LPOVERLAPPED lpOverlapped
)
{...}

Параметры

[in] s

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

[in] name

Указатель на
структура sockaddr , указывающая адрес, к которому нужно подключиться. Для IPv4 sockaddr содержит AF_INET для семейства адресов, IPv4-адреса назначения и порта назначения. Для IPv6 структура sockaddr содержит AF_INET6 для семейства адресов, IPv6-адрес назначения, порт назначения, а также может содержать дополнительные сведения о потоке IPv6 и область-id.

[in] namelen

Длина структуры sockaddr в байтах, на которую указывает параметр name .

[in, optional] lpSendBuffer

Указатель на буфер, который необходимо передать после установки соединения. Этот параметр является необязательным. Если параметр TCP_FASTOPEN включен в до вызова ConnectEx , то некоторые из этих данных могут отправляться во время установки подключения.

[in] dwSendDataLength

Длина (в байтах) данных, на которые указывает параметр lpSendBuffer . Этот параметр игнорируется, если параметр lpSendBuffer имеет значение NULL.

[out] lpdwBytesSent

При успешном возвращении этот параметр указывает на значение DWORD , указывающее количество байтов, отправленных после установки подключения. Отправленные байты передаются из буфера, на который указывает параметр lpSendBuffer . Этот параметр игнорируется, если параметр lpSendBuffer имеет значение NULL.

[in] lpOverlapped

Структура OVERLAPPED , используемая для обработки запроса. Параметр lpOverlapped должен быть указан и не может иметь значение NULL.

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

При успешном выполнении функция ConnectEx возвращает значение TRUE. При сбое функция возвращает значение FALSE. Используйте функцию WSAGetLastError для получения расширенных сведений об ошибке. Если вызов функции WSAGetLastError возвращает ERROR_IO_PENDING, операция успешно запущена и выполняется. В таких случаях вызов по-прежнему может завершиться ошибкой после завершения перекрывающейся операции.

Если возвращен код ошибки WSAECONNREFUSED, WSAENETUNREACH или WSAETIMEDOUT, приложение может вызвать ConnectEx, WSAConnect или снова подключиться к тому же сокету.

Код ошибки Описание
WSANOTINITIALISED
Перед использованием ConnectEx должен произойти успешный вызов функции WSAStartup.
WSAENETDOWN
Произошел сбой сетевой подсистемы.
WSAEADDRINUSE
Локальный адрес сокета уже используется, и сокет не помечен, чтобы разрешить повторное использование адреса с SO_REUSEADDR. Эта ошибка обычно возникает во время операции привязки , но она может быть отложена до вызова функции ConnectEx , если функция bind была вызвана с подстановочными знаками (INADDR_ANY или in6addr_any), указанным для локального IP-адреса. Конкретный IP-адрес должен быть неявно привязан функцией ConnectEx .
WSAEALREADY
Для указанного сокета выполняется вызов функции неблокировки connect, WSAConnect или ConnectEx .
WSAEADDRNOTAVAIL
Удаленный адрес не является допустимым адресом, например ADDR_ANY (функция ConnectEx поддерживается только для сокетов, ориентированных на подключение).
WSAEAFNOSUPPORT
Адреса из заданного семейства адресов не могут использоваться с этим сокетом.
WSAECONNREFUSED
Попытка подключения была отклонена.
WSAEFAULT
Параметр name, lpSendBuffer или lpOverlapped не является допустимой частью адресного пространства пользователя или параметр namelen слишком мал.
WSAEINVAL
Параметр s является несвязанным или прослушивающим сокетом.
WSAEISCONN
Сокет уже подключен.
WSAENETUNREACH
В настоящее время сеть недоступна с этого узла.
WSAEHOSTUNREACH
Сделана попытка выполнить операцию на сокете для недоступного хоста.
WSAENOBUFS
Буферное пространство недоступно; Не удается подключить сокет.
WSAENOTSOCK
Дескриптор не является сокетом.
WSAETIMEDOUT
Время ожидания попытки подключения истекло без установления соединения.

Комментарии

Функция ConnectEx объединяет несколько функций сокетов в один переход МЕЖДУ API и ядром. После успешного завершения вызова функции ConnectEx выполняются следующие операции:

  • Установлено новое подключение.
  • После установки подключения отправляется необязательный блок данных.

Для приложений, предназначенных для Windows Vista и более поздних версий, рекомендуется использовать функцию WSAConnectByList или WSAConnectByName , которая значительно упрощает проектирование клиентских приложений.

Функцию ConnectEx можно использовать только с сокетами, ориентированными на подключение. Сокет, переданный в параметре s , должен быть создан с типом сокета SOCK_STREAM, SOCK_RDM или SOCK_SEQPACKET.

Параметр lpSendBuffer указывает на буфер данных для отправки после установления соединения. Параметр dwSendDataLength указывает длину отправляемых данных в байтах. Приложение может запросить отправку большого буфера данных с помощью ConnectEx так же, как можно использовать функции send и WSASend . Но разработчикам настоятельно рекомендуется не отправлять огромный буфер в одном вызове с помощью ConnectEx, так как эта операция использует большой объем ресурсов системной памяти, пока не будет отправлен весь буфер.

Если функция ConnectEx выполнена успешно, было установлено подключение и все данные, на которые указывает параметр lpSendBuffer , были отправлены на адрес, указанный в структуре sockaddr , на которую указывает параметр name .

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

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

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

 

Сокеты, ориентированные на подключение, часто не могут завершить подключение немедленно, поэтому операция инициируется и функция немедленно возвращается с ошибкой ERROR_IO_PENDING или WSA_IO_PENDING. По завершении операции подключения и успешном или неудачном выполнении сообщается состояние с помощью механизма уведомления о завершении, указанного в lpOverlapped. Как и во всех перекрывающихся вызовах функций, в качестве механизма уведомления о завершении можно использовать события или порты завершения. Параметр lpNumberOfBytesTransferred функции GetQueuedCompletionStatus или GetOverlappedResult или WSAGetOverlappedResult указывает количество байтов, отправленных в запросе.

После успешного завершения функции ConnectEx дескриптор сокета можно передать только следующим функциям:

Если функция TransmitFile вызывается для ранее подключенного сокета с флагами TF_DISCONNECT и TF_REUSE_SOCKET, указанный сокет возвращается в состояние, в котором он не подключен, но все еще привязан. В таких случаях дескриптор сокета может быть передан функции ConnectEx в параметре s , но сокет нельзя использовать повторно в вызове функции AcceptEx . Аналогичным образом принятый сокет, повторно используемый с помощью функции TransmitFile , не может использоваться в вызове ConnectEx. Обратите внимание, что в случае повторно используемого сокета ConnectEx зависит от поведения базового транспорта. Например, сокет TCP может находиться в состоянии tcp-TIME_WAIT, что приводит к задержке вызова ConnectEx .

Когда функция ConnectEx возвращает значение TRUE, сокеты для подключенного сокета будут в состоянии по умолчанию. Сокет не включает ранее заданные свойства или параметры до тех пор, пока в сокете не будет задано SO_UPDATE_CONNECT_CONTEXT. Используйте функцию setsockopt , чтобы задать параметр SO_UPDATE_CONNECT_CONTEXT.

Пример:

//Need to #include <mswsock.h> for SO_UPDATE_CONNECT_CONTEXT

int iResult = 0;

iResult = setsockopt( s, SOL_SOCKET, SO_UPDATE_CONNECT_CONTEXT, NULL, 0 );

Функцию getsockopt можно использовать с параметром сокета SO_CONNECT_TIME, чтобы проверка, установлено ли соединение во время выполнения ConnectEx. Если соединение установлено, значение, возвращаемое в параметре optval , передаваемом функции getsockopt , равно количеству секунд, в течение которых был подключен сокет. Если сокет не подключен, возвращаемый параметр optval содержит 0xFFFFFFFF. Проверка соединения таким образом необходима, чтобы определить, были ли установлены соединения в течение определенного периода времени без отправки каких-либо данных; в таких случаях рекомендуется прервать такие подключения.

Пример:


//Need to #include <mswsock.h> for SO_CONNECT_TIME

int seconds;
int bytes = sizeof(seconds);
int iResult = 0;

iResult = getsockopt( s, SOL_SOCKET, SO_CONNECT_TIME,
                      (char *)&seconds, (PINT)&bytes );
if ( iResult != NO_ERROR ) {
    printf( "getsockopt(SO_CONNECT_TIME) failed with error: %u\n", 
        WSAGetLastError() );
}
else {
    if (seconds == 0xFFFFFFFF)
        printf("Connection not established yet\n");
    else
       printf("Connection has been established %ld seconds\n",
           seconds);
}

Примечание Если открывается сокет, выполняется вызов setsockopt , а затем выполняется вызов sendto , Windows Sockets выполняет неявный вызов функции привязки .
 

Если параметр address структуры sockaddr, на который указывает в параметре name , равен нулю, ConnectEx возвращает ошибку WSAEADDRNOTAVAIL. Любая попытка повторно подключить активное подключение завершится ошибкой с кодом WSAEISCONN.

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

Если функция DisconnectEx вызывается с флагом TF_REUSE_SOCKET , указанный сокет возвращается в состояние, в котором он не подключен, но все еще привязан. В таких случаях дескриптор сокета может быть передан функции ConnectEx в параметре s .

Интервал времени, который должен пройти, прежде чем TCP сможет освободить закрытое подключение и повторно использовать его ресурсы, называется состоянием TIME_WAIT или состоянием 2MSL. В течение этого времени подключение может быть повторно открыто по гораздо меньшим затратам для клиента и сервера, чем установка нового подключения.

Поведение TIME_WAIT указано в RFC 793, который требует, чтобы TCP поддерживал закрытое подключение в течение по крайней мере в два раза максимального времени существования сегмента (MSL) сети. При освобождении подключения его пара сокетов и внутренние ресурсы, используемые для сокета, можно использовать для поддержки другого подключения.

Windows TCP возвращается в состояние TIME_WAIT после закрытия подключения. Находясь в состоянии TIME_WAIT, пару сокетов нельзя использовать повторно. Период TIME_WAIT можно настроить, изменив следующий параметр реестра DWORD , представляющий TIME_WAIT период в секундах.

HKEY_LOCAL_MACHINE\Системы\CurrentControlSet\Услуги\TCPIP\Параметры\TcpTimedWaitDelay

По умолчанию msl имеет значение 120 секунд. Параметр реестра TcpTimedWaitDelay по умолчанию имеет значение 240 секунд, что в 2 раза больше максимального времени существования сегмента, равного 120 секундам или 4 минутам. Однако эту запись можно использовать для настройки интервала.

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

Этот параметр реестра можно задать в диапазоне от 0 до 300 секунд.

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

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

Требования

Требование Значение
Минимальная версия клиента Windows 8.1, Windows Vista [классические приложения | Приложения UWP]
Минимальная версия сервера Windows Server 2003 [классические приложения | Приложения UWP]
Целевая платформа Windows
Header mswsock.h

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

AcceptEx

DisconnectEx

ExitThread

GetOverlappedResult

GetQueuedCompletionStatus

ПЕРЕКРЫВАЮЩИХСЯ

ReadFile

TransmitFile

WSAConnect

WSAConnectByList

WSAConnectByName

WSAGetLastError

WSAIoctl

WSARecv

WSASend

WSAStartup

Функции Winsock

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

WriteFile

bind

closesocket

connect;

getsockopt

Recv

send

Sendto

setsockopt

sockaddr