Чтение онлайн

ЖАНРЫ

О чём не пишут в книгах по Delphi

Григорьев Антон Борисович

Шрифт:

 DWORD dwServiceFlgs4;

 DWORD dwProviderFlags;

 GUID ProviderId;

 DWORD dwCatalogEntryId;

 WSAPROTOCOLCHAIN ProtocolChain;

 int iVersion;

 int iAddressFamily;

 int iMaxSockAddr;

 int iMinSockAddr;

 int iSocketType;

 int iProtocol;

 int iProtocolMaxOffset;

 int iNetworkByteOrder;

 int iSecurityScheme;

 DWORD dwMessageSize;

 DWORD dwProviderReserved;

 TCHAR szProtocol[WSAPROTOCOL_LEN - 1];

} WSAPROTOCOL_INFO, *LPWSAPROTOCOL_INFO;

// *****
Описание на Delphi *****

TWSAProtocolChain = packed record

 ChainLen: Integer;

 ChainEntries: array[0..MAX_PROTOCOL_CHAIN - 1] of DWORD;

end;

//Структура на C++ содержит тип TCHAR, который, как мы

// говорили в главе 1, может означать как Char,

// так и WideChar, т.е. структура должна иметь

// два варианта описания: TWSAProtocolInfoA для

// однобайтной кодировки и TWSAProtocolInfo для

// двухбайтной. Соответственно, все функции

// использующие эту структуру, реализованы

// в системных библиотеках в двух вариантах.

// Здесь мы приводим только ANSI-вариант.

PWSAProtocolInfo = ^TWSAProtocolInfo;

TWSAProtocolInfo = packed record

 dwServiceFlags1: DWORD;

 dwServiceFlags2: DWORD;

 dwServicsFlags3: DWORD;

 dwServiceFlags4: DWORD;

 dwProviderFlags: DWORD;

 ProviderId: GUID;

 dwCatalogEntryId: DWORD;

 ProtocolChain: TWSAProtocolChain;

 iVersion: Integer;

 iAddressFamily: Integer;

 iMaxSockAddr: Integer;

 iMinSockAddr: Integer;

 iSocketType: Integer;

 iProtocol: Integer;

 iProtocolMaxOffset: Integer;

 iNetworkByteOrder: Integer;

 iSecurityScheme: Integer;

 dwMessageSize: DWORD;

 dwProviderReserved: DWORD;

 szProtocol: array [0..WSAPROTOCOL_LEN] of Char;

end;

Расшифровка полей типа

TWSAProtocolInfo
есть в MSDN, мы здесь не будем ее приводить.

Сама функция

WSAEnumProtocols
, которая позволяет получить список всех протоколов, провайдеры которых установлены на компьютере, приведена в листинге 2.37.

Листинг 2.37. Функция
WSAEnumProtocols

// ***** описание на C++ *****

int WSAEnumProtocols(LPINT lpiProtocols, LPWSAPROTOCOL_INFO lpProtocolBuffer, LPDWORD lpdwBufferLength);

// ***** Описание на Delphi *****

function WSAEnumProtocols(lpiProtocols: PInteger; lpProtocolBuffer: PWSAProtocolInfo; var BufferLength: DWORD): Integer;

Примечание

В старых версиях MSDN в описании этой функции есть небольшая опечатка: тип параметра

lpdwBufferLength
назван
LLPDWORD
вместо
LPDWORD
.

Библиотека WS2_32.dll придерживается тех же правил насчет ANSI- и Unicode-вариантов функций, что и другие системные библиотеки (см. разд. 1.1.12), поэтому в ней нет функции с именем

WSAEnumProtocols
, а есть
WSAEnumProtocolsA
и
WSAEnumProtocolsW
. Эти функции работают с разными вариантами структуры
WSAPROTOCOL_INFO
, которые различаются типом элементов в последнем массиве —
CHAR
или
WCHAR
.

Параметр

lpiProtocols
указывает на первый элемент массива, содержащего список протоколов, информацию о которых нужно получить. Если этот указатель равен
nil
, то возвращается информация обо всех доступных протоколах. Параметр
lpProtocolBuffer
содержит указатель на начало массива структур типа
TWSAProtocolInfo
. Программа должна заранее выделить память под этот массив. Параметр
BufferLength
при вызове должен содержать размер буфера
lpProtocolBuffer
в байтах (именно размер в байтах, а не количество элементов). После завершения функции сюда помешается минимальный размер буфера, необходимый для размещения информации обо всех запрошенных протоколах. Если это значение больше переданного, функция завершается с ошибкой.

Если параметр

lpiProtocols
не равен нулю, он должен содержать указатель на массив, завершающийся нулем. Следовательно, если количество протоколов, запрашиваемых программой, равно N, этот массив должен состоять из N+1 элементов, и первые N элементов должны содержать номера протоколов, а последний элемент — ноль.

В системе может быть установлено несколько провайдеров для одного протокола. В этом случае информация о каждом провайдере будет помещена в отдельный элемент массива. Из-за этого число задействованных элементов в массиве

lpProtocolBuffer
может превышать количество протоколов, определяемых параметром
lpiProtocols
.

К сожалению, полную информацию о том, каким протоколам какие номера соответствуют, в документации найти не удалось. Можно только сказать, что для получения информации о протоколе TCP в массив

lpiProtocols
необходимо поместить константу
IPPROTO_TCP
, о протоколе UDP — константу
IPPROTO_UDP
.

Возвращаемое функцией значение равно числу протоколов, информация о которых помещена в массив, если функция выполнена успешно, и

SOCKET_ERROR
, если при ее выполнении возникла ошибка. Конкретная ошибка определяется стандартным методом, с помощью
WSAGetLastError
. Если массив
lpProtocolBuffer
слишком мал для хранения всей требуемой информации, функция завершается с ошибкой
WSAENOBUFS
.

WinSock 1 содержит аналогичную по возможности функцию

EnumProtocols
, возвращающую массив структур
PROTOCOL_INFO
. Эта структура содержит меньше информации о протоколе, чем
WSAPROTOCOL_INFO
и, в отличие от последней, не используется никакими другими функциями WinSock. Несмотря на то, что функция
EnumProtocols
и структура
PROTOCOL_INFO
описаны в первой версии WinSock, модуль WinSock их не импортирует, при необходимости их нужно импортировать самостоятельно. Но функция
EnumProtocols
считается устаревшей, использовать ее в новых приложениях не рекомендуется, поэтому практически всегда, за исключением редких случаев, требующих совместимости с WinSock 1, лучше выбрать более современную функцию
WSAEnumProtocols
.

Поделиться с друзьями: