Функция WSAConnectByList (winsock2.h)
Функция WSAConnectByList устанавливает подключение к одной из коллекции возможных конечных точек, представленных набором целевых адресов (имена узлов и портов). Эта функция принимает все адреса назначения, переданные ей, и все исходные адреса локального компьютера, и пытается подключиться, используя все возможные сочетания адресов, прежде чем отказаться.
Эта функция поддерживает адреса IPv4 и IPv6.
Синтаксис
BOOL WSAConnectByList(
[in] SOCKET s,
[in] PSOCKET_ADDRESS_LIST SocketAddress,
[in, out] LPDWORD LocalAddressLength,
[out] LPSOCKADDR LocalAddress,
[in, out] LPDWORD RemoteAddressLength,
[out] LPSOCKADDR RemoteAddress,
[in] const timeval *timeout,
[in] LPWSAOVERLAPPED Reserved
);
Параметры
[in] s
Дескриптор, определяющий несвязанный и несвязанный сокет. Обратите внимание, что в отличие от других вызовов Winsock для установки соединения (например, WSAConnect), для функции WSAConnectByList требуется незавязанный сокет.
[in] SocketAddress
Указатель на структуру SOCKET_ADDRESS_LIST , представляющую возможные пары адреса назначения и портов для подключения к одноранговой точке. За заполнение номера порта в каждой структуре SOCKET_ADDRESS в SOCKET_ADDRESS_LIST отвечает приложение.
[in, out] LocalAddressLength
На входных данных — указатель на размер буфера LocalAddress в байтах , предоставленного вызывающим объектом. В выходных данных — указатель на размер (в байтах) SOCKADDR для локального адреса, хранящегося в буфере LocalAddress , заполненном системой после успешного завершения вызова.
[out] LocalAddress
Указатель на структуру SOCKADDR , которая получает локальный адрес подключения. Размер параметра точно совпадает с размером, возвращенным в LocalAddressLength. Это те же сведения, которые будут возвращены функцией getsockname . Этот параметр может иметь значение NULL. В этом случае параметр LocalAddressLength игнорируется.
[in, out] RemoteAddressLength
На входных данных — указатель на размер буфера RemoteAddress в байтах , предоставленного вызывающим объектом. На выходе — указатель на размер (в байтах) SOCKADDR для удаленного адреса, хранящегося в буфере RemoteAddress , заполненного системой после успешного завершения вызова.
[out] RemoteAddress
Указатель на структуру SOCKADDR , которая получает удаленный адрес подключения. Это те же сведения, которые будут возвращены функцией getpeername . Этот параметр может иметь значение NULL. В этом случае RemoteAddressLength игнорируется.
[in] timeout
Время (в миллисекундах) ожидания ответа от удаленного приложения перед прерыванием вызова. Этот параметр может иметь значение NULL , и в этом случае WSAConnectByList завершится после успешного установления подключения или после попытки подключения и сбоя для всех возможных пар "локальный—удаленный адрес".
[in] Reserved
Зарезервировано для будущей реализации. Этот параметр должен иметь значение NULL.
Возвращаемое значение
Если подключение установлено, WSAConnectByList возвращает значение TRUE , а параметры LocalAddress и RemoteAddress заполняются, если эти буферы были предоставлены вызывающим объектом.
Если вызов завершается сбоем, возвращается значение FALSE . Затем можно вызвать WSAGetLastError для получения расширенных сведений об ошибке.
Код возврата | Описание |
---|---|
|
Узел, переданный в качестве параметра nodename , был недостижим. |
|
В функцию передан недопустимый параметр. Параметр Reserved должен иметь значение NULL. |
|
Не удалось выделить достаточный объем памяти. |
|
В функцию передан недопустимый сокет. Параметр s не должен быть INVALID_SOCKET или NULL. |
|
Ответ от удаленного приложения не был получен до превышения времени ожидания . |
Комментарии
WSAConnectByList похож на функцию WSAConnectByName . Вместо одного имени узла и имени службы (порта) WSAConnectByList принимает список адресов (адресов узлов и портов) и подключается к одному из адресов. Функция WSAConnectByList предназначена для поддержки сценариев одноранговой совместной работы, в которых приложению необходимо подключиться к любому доступному узлу из списка потенциальных узлов. WSAConnectByList совместим с версиями IPv6 и IPv4.
Набор возможных назначений, представленный списком адресов, предоставляется вызывающим. WSAConnectByList не просто пытается подключиться к одному из возможных целевых адресов. В частности, функция принимает все удаленные адреса, переданные вызывающим абонентом, все локальные адреса, а затем пытается установить соединение с использованием пар адресов с наибольшей вероятностью успеха. Таким образом, WSAConnectByList не только гарантирует, что подключение будет установлено, если подключение возможно, но и сокращает время установки соединения.
Вызывающий объект может указать буферы и длину LocalAddress и RemoteAddress , чтобы определить локальные и удаленные адреса, для которых подключение было успешно установлено.
Параметр timeout позволяет вызывающей объекту ограничить время, затраченное функцией на установление соединения. На внутреннем сервере WSAConnectByList выполняет несколько операций (попытки подключения). В период между каждой операцией проверяется параметр времени ожидания , чтобы узнать, превышено ли время ожидания , и, если да, вызов прерывается. Обратите внимание, что отдельная операция (подключение) не прерывается после превышения времени ожидания , поэтому время ожидания вызова WSAConnectByList может занять больше времени ожидания, чем значение, указанное в параметре timeout .
WSAConnectByList имеет ограничения: он работает только для сокетов, ориентированных на подключение, таких как сокеты типа SOCK_STREAM. Функция не поддерживает перекрывающееся или неблокирующее поведение. WSAConnectByList будет блокироваться, даже если сокет находится в неблокирующем режиме. WSAConnectByList попытается подключиться (по одному) к различным адресам, предоставленным вызывающим абонентом. Возможно, каждая из этих попыток подключения может завершиться ошибкой с другим кодом ошибки. Так как может быть возвращен только один код ошибки, возвращенным значением является код ошибки из последней попытки подключения.
Чтобы разрешить передавать адреса IPv6 и IPv4 в одном списке адресов, принятом функцией, перед вызовом функции необходимо выполнить следующие действия:
- Функция setsockopt должна вызываться в сокете, созданном для семейства адресов AF_INET6, чтобы отключить параметр сокета IPV6_V6ONLY перед вызовом WSAConnectByList. Это достигается путем вызова функции setsockopt в сокете с параметром уровня , равным IPPROTO_IPV6 (см . IPPROTO_IPV6 Параметры сокета), параметру optname присвоено значение IPV6_V6ONLY, а значение параметра optvalue равно нулю.
- Все IPv4-адреса должны быть представлены в формате IPv6-адресов, сопоставленных с IPv4, что позволяет приложению только IPv6 взаимодействовать с узлом IPv4. Формат IPv6-адресов, сопоставленный с IPv4, позволяет представлять IPv4-адрес узла IPv4 в виде IPv6-адреса. IPv4-адрес закодирован в 32 бита IPv6-адреса низкого порядка, а 96-разрядные устройства высокого порядка содержат фиксированный префикс 0:0:0:0:0:0:FFFF. Формат IPv6-адресов, сопоставленный с IPv4, указан в RFC 4291. Дополнительные сведения см. в разделе www.ietf.org/rfc/rfc4291.txt. Макрос IN6ADDR_SETV4MAPPED в Mstcpip.h можно использовать для преобразования IPv4-адреса в требуемый формат IPv6-адресов.
Массивы указателей, передаваемые в параметре SocketAddressList , указывают на массив SOCKET_ADDRESS структур, которые являются универсальным типом данных. Параметры RemoteAddress и LocalAddress также указывают на структуры SOCKADDR . При вызове WSAConnectByList ожидается, что в этих параметрах будет передаваться тип адреса сокета, относящегося к используемому сетевому протоколу или семейству адресов. Таким образом, для IPv4-адресов указатель на структуру sockaddr_in будет приведен к указателю на SOCKADDR при передаче в качестве параметра. Для IPv6-адресов указатель на структуру sockaddr_in6 будет приведен к указателю на SOCKADDR при передаче в качестве параметра. Параметр SocketAddressList может содержать указатели на сочетание адресов IPv4 и IPv6. Таким образом, некоторые SOCKET_ADDRESS указатели могут быть sockaddr_in структуры, а другие могут быть sockaddr_in6 структуры. Если предполагается, что можно использовать IPv6-адреса, то параметры RemoteAddress и LocalAddress должны указывать на sockaddr_in6 структуры и приводиться к структурам SOCKADDR . Параметры RemoteAddressLength и LocalAddressLength должны представлять длину этих больших структур.
Когда функция WSAConnectByList возвращает значение 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 );
Windows 8.1 и Windows Server 2012 R2: эта функция поддерживается для приложений Магазина Windows на Windows 8.1, Windows Server 2012 R2 и более поздних версий.
Примеры
Установите подключение с помощью WSAConnectByList.
#ifndef UNICODE
#define UNICODE
#endif
#define WIN32_LEAN_AND_MEAN
#include <winsock2.h>
#include <Ws2tcpip.h>
#include <stdio.h>
// Link with ws2_32.lib
#pragma comment(lib, "Ws2_32.lib")
SOCKET
OpenAndConnect(SOCKET_ADDRESS_LIST *AddressList)
{
SOCKET ConnSocket = INVALID_SOCKET;
int ipv6only = 0;
int iResult;
BOOL bSuccess;
SOCKADDR_STORAGE LocalAddr = {0};
SOCKADDR_STORAGE RemoteAddr = {0};
DWORD dwLocalAddr = sizeof(LocalAddr);
DWORD dwRemoteAddr = sizeof(RemoteAddr);
ConnSocket = socket(AF_INET6, SOCK_STREAM, 0);
if (ConnSocket == INVALID_SOCKET){
return INVALID_SOCKET;
}
iResult = setsockopt(ConnSocket, IPPROTO_IPV6,
IPV6_V6ONLY, (char*)&ipv6only, sizeof(ipv6only) );
if (iResult == SOCKET_ERROR){
closesocket(ConnSocket);
return INVALID_SOCKET;
}
// AddressList may contain IPv6 and/or IPv4Mapped addresses
bSuccess = WSAConnectByList(ConnSocket,
AddressList,
&dwLocalAddr,
(SOCKADDR*)&LocalAddr,
&dwRemoteAddr,
(SOCKADDR*)&RemoteAddr,
NULL,
NULL);
if (bSuccess){
return ConnSocket;
} else {
return INVALID_SOCKET;
}
}
Требования
Минимальная версия клиента | Windows 8.1, Windows Vista [классические приложения | Приложения UWP] |
Минимальная версия сервера | Windows Server 2003 [классические приложения | Приложения UWP] |
Целевая платформа | Windows |
Header | winsock2.h |
Библиотека | Ws2_32.lib |
DLL | Ws2_32.dll |