Возвращаемое функцией значение равно числу протоколов, информация о которых помещена в массив, если функция выполнена успешно, и SOCKET_ERROR
, если при ее выполнении возникла ошибка. Конкретная ошибка определяется стандартным методом, с помощью WSAGetLastError
. Если массив lpProtocolBuffer
слишком мал для хранения всей требуемой информации, функция завершается с ошибкой WSAENOBUFS
.
WinSock 1 содержит аналогичную по возможности функцию EnumProtocols
, возвращающую массив структур PROTOCOL_INFO
. Эта структура содержит меньше информации о протоколе, чем WSAPROTOCOL_INFO
и, в отличие от последней, не используется никакими другими функциями WinSock. Несмотря на то, что функция EnumProtocols
и структура PROTOCOL_INFO
описаны в первой версии WinSock, модуль WinSock их не импортирует, при необходимости их нужно импортировать самостоятельно. Но функция EnumProtocols
считается устаревшей, использовать ее в новых приложениях не рекомендуется, поэтому практически всегда, за исключением редких случаев, требующих совместимости с WinSock 1, лучше выбрать более современную функцию WSAEnumProtocols
.
2.2.4. Новые функции
В этом разделе мы рассмотрим некоторые новые функции, появившиеся в WinSock 2. Большинство из них позволяет выполнять действия, уже знакомые нам из предыдущих разделов, но предоставляет большие возможности, чем стандартные сокетные функции.
Для создания сокета предназначена функция WSASocket
со следующим прототипом (листинг 2.38).
WSASocket
// ***** Описание на C++ *****
SOCKET WSASocket(int af, int SockType, int protocol, LPWSAPROTOCOL_INFO lpProtocolInfo, GROUP g, DWORD dwFlags);
// ***** Описание на Delphi *****
function WSASocket(AF, SockType, Protocol: Integer; lpProtocolInfo: PWSAProtocolInfo; g: TGroup; dwFlags: DWORD): TSocket;
Первые три параметра совпадают с тремя параметрами функции socket
. Параметр lpProtocolInfo
указывает на структуру TWSAProtocolInfo
, содержащую информацию о протоколе, для которого создается сокет. Если этот указатель равен nil
, функция создает сокет на основании первых трёх параметров так же, как это делает функция socket
. С другой стороны, если этот параметр не равен nil
, то структура, на которую он указывает, содержит всю информацию, необходимую для создания сокета, поэтому первые три параметра должны быть равны константе FROM_PROTOCOL_INFO
(-1). Параметр g
зарезервирован для использования в будущем и должен быть равен нулю (тип TGroup
совпадает с DWORD
). Последний параметр dwFlags
определяет, какие дополнительные возможности имеет создаваемый сокет. Вызов функции socket
эквивалентен вызову функции WSASocket
с флагом WSA_FLAG_OVERLAPPED
, который показывает, что данный сокет можно использовать для перекрытого ввода-вывода
В случае TCP и UDP функция WSASocket
дает следующие преимущества по сравнению с функцией socket
. Во-первых, через параметр lpProtocolInfo
появляется возможность явно указать провайдера, который будет выбран программой. Во-вторых, если программа не использует перекрытый ввод-вывод, можно создавать сокеты без флага WSA_FLAG_OVERLAPPED
, экономя при этом некоторое незначительное количество ресурсов. Кроме того, как это будет обсуждаться далее, с помощью WSASocket
две разных программы могут работать с одним и тем же сокетом.
Функция WSAConnect
— это более мощный аналог connect
. Ее прототип приведен в листинге 2.39.
WSAConnect
и связанные с ней типы// ***** Описание на C++ *****
int WSAConnect(SOCKET s, const struct sockaddr FAR* name, int name len, LPWSABUF lpCallerData, LPWSABUF lpCalleeData, LPQOS lpSQOS, LPQOS lpGQOS);
typedef struct __WSABUF {
u_long len;
char FAR *buf;
} WSABUF, FAR* LPWSABUF;
// ***** Описание на Delphi ******