Главная страница

Программирование в сетях Windows. Э. Джонс, Д. Оланд


Скачать 2.88 Mb.
НазваниеЭ. Джонс, Д. Оланд
АнкорПрограммирование в сетях Windows.pdf
Дата12.10.2017
Размер2.88 Mb.
Формат файлаpdf
Имя файлаПрограммирование в сетях Windows.pdf
ТипКнига
#9346
страница26 из 50
1   ...   22   23   24   25   26   27   28   29   ...   50
Команда SIO_GET_QOS
Функция WSAIoctl (версия Winsock 2+) возвращает значения типа QOS Эта ioctl-команда получает структуру QOS, связанную с сокетом Предоставленный буфер должен быть достаточно объемным, чтобы вместить в себя эту струк- туру целиком Между тем ее размеры в ряде случаев превышают sizeof(QOS),
так как могут содержать информацию, специфичную для поставщика Под- робнее о QoS — в главе 12 Если эта ioctl-команда используется на сокете, се- мейство адресов которого не поддерживает QoS, выдается ошибка WSAENOP-
ROTO0PT Этот параметр и SIO_SET_QOS досгупны только на платформах,
обеспечивающих QoS-совместимый транспорт, таких как Windows 98 и Win- dows 2000
Команда SIOJSETJ3OS
Эта ioctl-команда составляет пару для SIO_GET_QOS Входной параметр для функции WSAIoctl (версия Winsock 2+) — структура QOS, которая определя- ет требования к пропускной способности для данного сокета Выходные значения не возвращаются Этот параметр и SIO_GET_QOS доступны только на платформах, обеспечивающих QoS-совместимый транспорт, таких как
Windows 98 и Windows 2000
Команда SIO „MULTIPOINTJ.OOPBACK
Функция WSAIoctl (версия Winsock 2+) принимает и возвращает значение типа BOOL и определяет, будут ли многоадресные данные возвращены на сокет При отправке группе данные по умолчанию поступают в очередь вхо- дящих сообщений исходного сокета Естественно, такая петля образуется,
только если сокет также входит в целевую многоадресную группу В настоя- щее время это поведение характерно только для IP, но не для ATM Для от- ключения петли передайте FALSE во входном параметре ipvInBujfer Чтобы получить текущее значение этого параметра, оставьте входное значение рав- ным NULL, а в качестве выходного параметра укажите булеву переменную
Команда SIO_MULTICAST_$COPE
Функция WSAIoctl (версия Wmsock 2+) принимает и возвращает значение типа mt Эта ioctl-команда контролирует время жизни (или область распро- странения) многоадресных данных Область распространения — это коли- чество маршрутизируемых сегментов сети, которые разрешено пересечь данным Значение по умолчанию — 1 Когда многоадресный пакет попада- ет в Маршрутизатор, значение TTL уменьшатся на 1 Когда TTL достигает 0,
пакет отбрасывается Чтобы задать это значение, передайте целое с желае-

2 7 8 ЧАСТЬ И Интерфейс прикладного программирования Winsock мым TTL как ipvInBuffer. Если же вы хотите просто получить текущее значе- ние TTL, вызовите WSAIoctl с ipvOutBuffer, указывающим на целое число.
Команда SIO_KEEPALIVE_VALS
Функция WSAIoctl (версия Winsock 2+) принимает и возвращает значения типа tcp_keepalive. Эта ioctl-команда позволяет включить передачу сообще- ний о сохранении соединения (keepalive) для TCP для каждого соединения и задать интервал между их отправкой. Параметр сокета SO_KEEPAUVE также включает передачу сообщений о сохранении соединения TCP, но интервал между ними задается в системном реестре, модификация которого затронет все процессы на компьютере. Команда SIO_KEEPAUVE_VALS позволяет задать интервал отдельно для каждого сокета. Для этого следует инициализировать на данном сокете структуру tcp_keepalive и предать ее как буфер ввода:
struct tcp_keepalive
{
u_long onoff;
u_long keepalivetime;
u_long keepaliveinterval;
}
Значение полей структуры keepalivetime и keepaliveinterval идентичны значениям реестра, которые мы уже обсуждали в разделе, посвященном па- раметру SO_KEEPALIVE. Для запроса текущих значений вызовите WSAIoctl с
командой SIO_KEEPALIVE_VALS и предоставьте структуру tcp_keepalive в каче- стве буфера вывода. Эта команда доступна только в Windows 2000.
Команда SIO_RCVALL
Функция WSAIoctl (версия Winsock 2+) принимает значение типа unsigned int,
выходных параметров нет. Использование этой команды со значением TRUE
позволяет данному сокету получать все IP-пакеты в сети. Для этого необхо- димо передать описатель сокета в WSAIoctl. Нужно, чтобы сокет был из семей- ства адресов AFJNET, тип — SOCK_RAW, протокол — IPPROTOJP. Сокет дол- жен быть связан с явным локальным интерфейсом, то есть нельзя создать привязку INADDR_ANY.
После привязки сокета и задания ioctl-команды вызовы recv/WSARecv воз- вращают IP-дейтаграммы. Помните, что для дейтаграмм следует предусмот- реть достаточно вместительный буфер. Поскольку поле суммарного разме- ра заголовка IP — 16-битная величина, максимальный теоретический пре- дел - 65 535 байт, однако на практике максимальная единица передачи
(maximum transmission unit, MTU) в сетях гораздо меньше.
Использование SIO_RCVALL требует привилегий администратора на локаль- ном компьютере. К тому же эта ioctl-команда действует только на компьюте- ре с Windows 2000. Образец приложения на прилагаемом диске — Rcvall.c,
иллюстрирует использование этой и двух других ioctl-команд S1O_RCVALL.
I

Г Л А В А 9 Параметры сокета и команды управления вводом-выводом 279
Команда SIO_RCVALL_MCAST
Эта команда похожа на SIORCVALL и также получает все многоадресные па- кеты в сети. Функция WSAIoctl (версия Winsock 2+) принимает значение типа
unsigned int, выходных параметров нет. Применяются те же правила исполь- зования, что и для SIO_RCVALL: сокет, переданный в WSAIoctl, также должен быть создан под протокол IPPROTOJGMP. Единственное отличие.- возвраща- ется только многоадресный IP-трафик, а не все IP-пакеты. Это означает, что возвращаются только IP-пакеты с адресов 224.0.0.0 — 239-255.255.255. Эта ioctl-команда доступна только в Windows 2000.
Команда SIOJtCVALLJGMPMCAST
Эта ioctl-команда тоже напоминает SIOJICVALL, включая то, что сокет, пере- данный в WSAIoctl, должен быть создан под протокол IPPROTOJGMP. Функ- ция WSAIoctl (версия Winsock 2+) принимает значение типа unsigned int, вы- ходных параметров нет. Но по этой команде возвращаются только все IGMP- пакеты. Инструкции по использованию этого параметра вы найдете в раз- деле по SIO_RCVALL. Эта команда доступна только в Windows 2000.
Команда
Обе функции (версия Winsock 2+) принимают значения типа SOCKADDR (вы- ходных параметров нет) и определяют, были ли считаны ООВ-данные. Эта ioctl-команда позволяет найти адрес локального интерфейса, который сле- дует использовать при отправке данных на удаленный компьютер. Адрес удаленной машины предоставляют в виде структуры SOCKADDR, как пара- метр ipvInBuffer. Буфер ipvOutBuffer должен быть достаточно большим, что- бы вместить массив из одной или более структур SOCKADDR, описывающих доступные локальные интерфейсы. Эту команду можно использовать для одноадресных или многоадресных конечных точек, а возвращенный интер- фейс — в последующих вызовах bind.
В основе команды SIO_ROUTING_INTERFACE_QUERY — plug-and-play воз- можности Windows 2000. Пользователь может вставлять (вынимать) сетевой адаптер формата PCMCIA, что повлияет на доступные приложению интер- фейсы. Учтите это в приложении для Windows 2000.
Приложения не могут полагаться на постоянство информации, возвра- щенной SIO_ROUTING INTERFACE_QUERY. Так что используйте ioctl-команду
SIO_ROUTING'INTERFACE_CHANGE, которая уведомит приложение о смене интерфейсов — тогда еще раз вызовите SIO_ROUTINGJNTERFACE_QUERY,
чтобы освежить информацию.
Команда SIO_ROUTING_INTERFACE_CHANGE
Эта ioctl-команда отправляет уведомление, когда изменился интерфейс для конечной точки, и таким образом помогает быть в курсе изменений на ло- кальном интерфейсе маршрутизации, используемом для доступа к указанно- му удаленному адресу. При применении этой команды структура SOCKADDR
Для удаленного адреса передается в буфер ввода, и после успешного завер-

280
ЧАСТЬ II Интерфейс прикладного программирования Winsock шения никакие данные не возвращаются. Впрочем, если по каким-то причи- нам, интерфейс для этого маршрута изменится, то приложение будет опо- вещено и сможет вызвать SIO ROUTINGJNTERFACE_QUERY, чтобы опреде- лить, какой интерфейс использовать дальше.
Существует несколько способов вызова этой команды. Если сокет — бло- кирующий, то вызов WSAIoctl не завершится до момента смены интерфейса.
В ином случае вернется ошибка WSAEWOULDBLOCK. Затем приложение ожи- дает событий изменения маршрута, вызывая WSAEventSelect или WSAAsyncSetect
с флагом FD_ROUTINGJNTERFACE_CHANGE, заданным в битовой маске сете- вого события. Перекрытый ввод-вывод тоже можно использовать: предос- тавьте описатель события в структуре WSAOVERLAPPED, которая освободит- ся после смены маршрутизации.
Адрес, указанной в структуре ввода SOCKADDR, задают явно или исполь- зуя шаблон INADDR_ANY — тогда вы узнаете о любых изменениях маршру- тизации. Поскольку информация о маршрутизации довольно статична, в поставщиках есть параметр для игнорирования информации, предоставляе- мой приложениями в буфер ввода. В этом случае поставщики просто отсы- лают уведомление после каждого изменения интерфейса. В итоге лучше за- регистрироваться для получения уведомлений о любом изменении и просто вызывать SIO_ROUTING_INTERFACE_QUERY, чтобы проверить, влияют ли эти изменения на приложение.
Команда SIO_ADDRESS_UST_QUERY
Эта ioctl-команда используется для получения списка адресов локального транспорта, соответствующих семейству протоколов сокета, с которым мо- жет связаться приложение. Функция WSAIoctl (версия Winsock 2+) не имеет значений ввода. Буфер вывода — структура SOCKET_ADDRESS_LIST:
typedef struct _SOCKET_ADDRESS_LIST
INT iAddressCount;
SOCKET_ADDRESS Address[1];
} SOCKET_ADDRESS_LIST, FAR * LPSOCKET_ADDRESS_LIST;
typedef struct _SOCKET_ADDRESS
LPSOCKADDR lpSockaddr;
INT iSockaddrLength;
SOCKET_ADDRESS, »PSOCKET_ADDRESS, FAR
LPSOCKET_ADDRESS;
В поле iAddressCount возвращается количество адресных структур в спис- ке, а поле Address — это массив адресов, специфичных для семейства про- токолов.
В plug-and-play среде Win32 количество действительных адресов может изменяться динамически, поэтому приложениям не следует полагаться на постоянство информации, полученной от этой ioctl-команды. Так, приложе- ния должны сначала вызвать SIO_ADDRESSJJST_QUERYрдя информации о те- кущих интерфейсах, а затем — SIO_ADDRESS_UST_CHANGE для получения

Г Л А В А 9 Параметры сокета и команды управления вводом-выводом 281
уведомлений о будущих изменениях. Если список адресов изменится, то при- ложение должно повторить запрос.
Если размер предоставленного буфера не достаточен, то WSAIoctl вернет ошибку WSAEFAULT, а параметр lebBytesRetumed — покажет требуемый раз- мер буфера.
Команда SIO_ADDRESS_UST_CHANGE
Приложение использует эту команду для получения уведомления об измене- ниях в списке адресов локального транспорта для семейства протоколов дан- ного сокета, с которым может связаться приложение. Функция WSAIoctl (вер- сия Winsock 2+) не принимает никаких значений для ввода, и после ее успеш- ного завершения параметры вывода не содержат никакой информации.
Существует несколько способов вызова этой команды. Если сокет — блоки- рующий, то вызов WSAIoctl не завершится до момента смены интерфейса. Если же сокет не в блокирующем режиме, вернется ошибка WSAEWOULDBLOCK. За- тем приложение ожидает событий изменения маршрута, вызывая WSAEventSelect
или WSAAsyncSelect с флагом FDJiOUTINGJNTERFACEjOHANGE, заданным в би- товой маске сетевого события. Перекрытый ввод-вывод тоже можно использо- вать: предоставьте описатель события в структуре WSAOVERIAPPED, которая освободится после смены маршрутизации.
Команда SIOJGETJNTERFACEJ.IST
Эта ioctl-команда определена в Ws2tcpip.h. Она использует функцию WSAIoctl
(версия Winsock 2+) для возврата информации о каждом интерфейсе на ло- кальном компьютере. Вводить ничего не требуется, но по завершении воз- вращается массив структур INTERFACEJNFO:
typedef struct _INTERFACE_INFO
i u_long
sockaddr_gen
sockaddr_gen
sockaddr_gen
> INTERFACE_INFO,
HFlags; /• Флаги интерфейса */
iiAddress; /* Адрес интерфейса */
HBroadcastAddress; /* Широковещательный адрес */
iiNetmask; /* Сетевая маска */
FAR • LPINTERFACE_INFO;
«define IFFJJP
«define IFF.BROADCAST
«define IFF.LOOPBACK
«define IFF_POINTTOPOINT
«define IFF_MULTICAST
typedef union sockaddr_gen
0x00000001 /* Интерфейс работает
0x00000002 /• Широковещание поддерживается
0x00000004 /• Это петельный интерфейс
0x00000008 /• Это интерфейс "точка-точка"
V
*/
*/
V
0x00000010 /• Поддерживается многоадресная рассылка •/
s t r u c t sockaddr Address;
struct sockaddr_in Addressln;
struct sockaddr_in6 Addressln6;
> sockaddr.gen;

2 8 2 ЧАСТЬ II Интерфейс прикладного программирования Winsock
Элемент UFlags возвращает битовую маску флагов, указывающих, рабочий ли это интерфейс (JFFJJP), а также поддерживается ли широковещание
{IFF^BROADCAST) или многоадресная рассылка (IFF MULTICAST). Также вид- но, является ли интерфейс петельным (loopback) — IFF LOOPBACK, или слу- жит для связи «точка-точка» — IFFPOINTTOPO1NT. Три других поля содержат адрес интерфейса, адрес широковещания и соответствующую сетевую маску.
loctl-команды Secure Socket Layer
Команды Secure Socket Layer (SSL) действуют только в Windows СЕ. В насто- ящий момент Windows 9x, NT и 2000 не содержат SSL-совместимого постав- щика. Поэтому их поддерживает только Winsock 1.
Команда SOJSSL_GET_CАР ABILITIES
Функция WSAIoctl не имеет выходных значений. Команда SO_SSL_GET CA-
PABILITIES получает набор флагов, описывающих возможности поставщика защиты Windows Sockets. Буфер вывода должен быть указателем на битовое поле DWORD. На данный момент определен только флаг SO_CAP_CUENT.
Команда SO_SSL_GET_FLAGS
Функция WSAIoctl возвращает флаги, специфичные для 5-канала, связанного с сокетом. Она не имеет значений ввода, а буфер вывода должен быть ука- зателем на битовое поле DWORD. Перечень допустимых флагов вы найдете в описании SOJSLJETFLAGS.
Команда SO_SSL_SET_FLAGS
Функция WSAIoctl не имеет выходных значений и задает флаги, специфич- ные для 5-канала, связанного с сокетом. Буфер ввода должен быть указателем на битовое поле DWORD. На данный момент определен только флаг SSL_
FLAGJDEFERHANDSHAKE, который позволяет приложениям отправлять и получать открытый текст до переключения на шифрованный. Этот флаг не- обходим для установки связи через прокси-серверы.
Как правило, поставщик защиты Windows Sockets выполняет безопасное согласование связи в рамках функции connect. Впрочем, если этот флаг вклю- чен, то согласование связи откладывается до момента, пока приложение не выдаст контрольный код SO_SSL_PERFORM_HANDSHAKE. После согласования флаг сбрасывается.
Команда SO_SSL_GET_PROTOCOLS
Функция WSAIoctl не имеет выходных значений. Команда SO_SSL_GET_PR°-
TOCOLS получает список протоколов, которые поставщик поддерживает на этом сокете. Буфер вывода должен быть указателем на структуру SSLPROTOCOLS-.
typedef struct _SSLPROTOCOL
{
DWORD dwProtocol;
DWORD dwVersion;

Г Л А В А 9 Параметры сокета и команды управления вводом-выводом 283
DWORD dwFlags;
} SSLPROTOCOL, «LPSSLPROTOCOL;
typedef struct _SSLPROTOCOLS
{
DWORD dwCount;
SSLPROTOCOL ProtocolList[1];
} SSLPPOTOCOLS, FAR .LPSSLPROTOCOLS;
Действительные протоколы для поля dwProtocol: SSL_PROTOCOL_SSL2,
SSL_PROTOCOL_SSL3 и SSL_PROTOCOL_PCT1.
Команда SO_SSL_SET_PROTOCOLS
Функция WSAIoctl не имеет выходных значений и задает список протоколов,
которые должен поддерживать поставщик на этом сокете. Буфер ввода ука- зывает на уже описанную структуру SSLPROTOCOLS.
Команда SO_SSL_SETJ/ALIDATE_CERT_HOOK
Эта ioctl-команда задает для сокета указатель на функцию проверки для при- ема SSL-сертификатов. Функция WSAIoctl не имеет выходных параметров,
это функция обратного вызова, применяемая поставщиком защиты Windows
Sockets, когда он получает набора реквизитов от удаленной стороны. Буфер ввода должен быть указателем на структуру SSLVALIDATECERTHOOK:
typedef struct
{
SSLVALIDATECERTFUNC HookFunc;
LPVOID pvArg;
} SSLVALIDATECERTHOOK, «PSSLVALIDATECERTHOOK;
Поле HookFunc — указывает на функцию обратного вызова, проверяю- щую сертификат, apvArg — на данные, специфичные для приложения. Этот указатель приложения могут использовать в своих целях.
Команда SO_SSL_PERFORM_HANDSHAKE
Эта ioctl-команда инициирует надежное согласование на подключенном со- кете, для которого перед соединением был задан флаг SSL_FLAG_DEFER_
HANDSHAKE. Буферы данных не требуются, но флаг SSL_FLAG_DEFER_HAN-
DSHAKE будет сброшен.
loctl-команды для ATM
Описанные в этом разделе ioctl-команды специфичны для семейства прото- колов ATM. Они довольно просты и в основном касаются получения коли- чества АТМ-устройств и АТМ-адресов локальных интерфейсов. Подробнее о механизмах адресации ATM — в главе 6.
Команда SIO_GET_NUMBER_OF_A TM_DEVICES
Функция WSAIoctl (версия Winsock 2+) не имеет значений для ввода. Коман- да SIO_GET_NUMBER_OF_ATM_DEVICES заполняет буфер вывода, на который

2 8 4 ЧАСТЬ II Интерфейс прикладного программирования Winsock ссылается IpvOutBuffer, данными типа DWORD, содержащими количество
ATM-устройств в системе. Каждое устройство распознается по уникальному идентификатору, в диапазоне от О до п—\, где п — количество устройств,
возвращенных этой ioctl-командой.
Команда SIO_GET_ATM_ADDRESS
С помощью этой команды функция WSAIoctl (версия Winsock 2+) получает локальный ATM-адрес, связанный с указанным устройством. Идентификатор устройства типа DWORD задается в буфере ввода, а буфер вывода, на кото- рый ссылается ipvOutBuffer, заполнен структурой ATM_ADDRESS, содержащей локальный ATM-адрес, годный для использования с bind.
Команда SIO_ASSOCIATE_PVC
Эта ioctl-команда с помощью функции WSAIoctl (версия Winsock 2+) связы- вает сокет с постоянным виртуальным каналом связи (permanent virtual circuit, PVC), указанным в буфере ввода, который содержит структуру АТМ_
PVCPARAMS. Сокет должен быть из семейства адресов AF_ATM. Параметров вывода нет. После успешного возврата из функции приложение способно начать отправку и прием данных, как если бы было установлено соединение.
Структура ATM_PVC_PARAMS определена таю
<
ATM_CONNECTION_ID PvcConnectionld;
QOS PvcQos;
} ATM_PVC_PARAMS;
typedef struct
{
DWORD DeviceNumber;
DWORD VPI;
DWORD VCI;
> ATM_CONNECTION_ID;
Команда SIO_GET_ATM_CONNECTIONJD
Обе функции (версия Winsock 2+) определяют, были ли считаны ООВ-дан- ные. Команда SIOjSET ATM CONNECTIONJD получает идентификатор ATM- соединения, связанного с сокетом. После удачного возврата из этой функ- ции буфер вывода, на который ссылается IpvOutBuffer, заполняется структу- рой ATM_CONNECTION_ID
t
содержащей номер устройства и значения VPI/
VCI, которые были заданы ранее для SIO ASSOCIATE_PVC.

Г Л А В А 9 Параметры сокета и команды управления вводом-выводом 285
Резюме
Такое огромное разнообразие параметров сокета и ioctl-команд может на первый взгляд показаться излишним, но ведь они дают приложениям дос- туп к характеристикам, специфичным для протоколов, а также позволяют тонко настраивать приложения. В ряде случаев: например, с AppleTalk или
IrDA, — приложение использует один или несколько параметров сокета или ioctl-команд. Но даже тогда, как правило, одновременно применяется лишь незначительная часть этих параметров. Конечно, недостаток в том, что не все параметры сокета и ioctl-команды доступны на всех платформах Win- dows. Это усложняет создание переносимых приложений.
•1, +
> • ( ' • ;
• н

Г Л А В А
1 О
Регистрация и разрешение имен
В этой главе обсуждается независимая от протокола модель регистрации и разрешения имен, реализованная в Winsock 2. (Метод, использовавшийся в
Winsock 1, устарел, и мы не будем его рассматривать.) Сначала мы обсудим общие принципы разрешения и регистрации имен, затем перейдем к раз- личным моделям и описанию функций, предоставляемых протоколом Win- sock 2 для разрешения имен. Мы также расскажем, как зарегистрировать службу, чтобы другие пользователи могли ее найти.
Введение
Регистрация имен подразумевает сопоставление дружественного имени с зависимым от протокола адресом: например, имени узла с его IP-адресом.
Большинству людей трудно запомнить такой адрес рабочей станции, как
«157.54.185-186». Они предпочитают давать компьютерам более удобные для запоминания имена, например, «Ajonesl». В протоколе IP соответствие IP- адресов именам обеспечивает служба Domain Name System (DNS). Другие протоколы предоставляют свои способы привязки используемых ими адре- сов к дружественным именам.
Требуется не только регистрировать и разрешать имена компьютеров, но также связывать адрес сервера Winsock, чтобы клиенты могли получать его для подключения к серверу. Например, сервер выполняется на порту номер
5000 компьютера с адресом 157.64.185.186. Если он всегда выполняется толь- ко на данной системе, можно жестко задать его адрес в клиентском прило- жении.
Но как быть, если необходим более динамичный сервер, способный вы- полняться на нескольких компьютерах — например, отказоустойчивое рас- пределенное приложение? В случае отказа или перегруженности одно- го из серверов можно запустить экземпляр приложения на другой системе.
Выяснить при этом, где же выполняются серверы, достаточно трудно. В иде- але вам нужна возможность регистрировать свой отказоустойчивый рас-
пределенный сервер (Fault Tolerant Distributed Server) с несколькими адреса- ми, а также динамически обновлять зарегистрированную службу и ее адреса.
Именно для этого и существуют регистрация и разрешение имен. В этой главе мы рассмотрим функции Winsock для регистрации и разрешения имен распределенного сервера.

Г Л А В А 10 Регистрация и разрешение имен 287
Модели пространства имен
Прежде всего рассмотрим различные модели пространства имен, используе- мые большинством протоколов. Пространство имен позволяет связать про- токол и его атрибуты адресации с дружественным именем. К наиболее рас- пространенным пространствам имен относятся DNS (используется прото- колом IP) и NDS (NetWare Directory Services, используется протоколом IPX)
компании Novell. Они сильно различаются как по организации, так и по ре- ализации. Некоторые их свойства очень важны и помогают понять, как осу- ществляется регистрация и разрешение имен с помощью Winsock.
Существует три типа пространств имен: динамическое, статичное и по-
стоянное. Динамическое пространство имен позволяет регистрировать све- дения о службе на лету. Помимо прочего, это означает, что клиенты могут вести поиск службы в период выполнения. Обычно динамическое простран- ство имен периодически осуществляет широковещательную рассылку све- дений о службе, извещая клиентов о ее постоянной доступности. В качестве примера динамических пространств имен можно назвать Service Advertising
Protocol (SAP), который используется в средах Netware, и Name Binding Pro- tocol (NBP) — применяется протоколом AppleTalk.
Статичные пространства имен — наименее гибкий из всех трех типов.
Для регистрации службы в этом пространстве имен ее необходимо предва- рительно зарегистрировать вручную. Это означает, что зарегистрировать имя в статичном пространстве имен с помощью функций Winsock невоз- можно — Winsock включает лишь функции для разрешения имен. Пример статичного пространства имен — DNS, где вы вручную вводите IP-адреса и имена компьютеров в файл, который используется службой DNS для обра- ботки запросов на разрешение имени.
Постоянные пространства имен, как и динамические, позволяют служ- бам регистрировать сведения о себе на лету. Но в отличие от динамических,
постоянные пространства хранят сведения о регистрации на энергонезави- симых носителях, например, в файлах или на дисках. Постоянное простран- ство имен удаляет запись о службе только при получении от нее соответствующего запроса. Преимущества постоянного пространства — гиб- кость и отсутствие постоянной широковещательной рассылки сведений о доступности служб. Недостаток — если служба плохо написана, она может отключиться, не передав компоненту доступа (поставщику) к пространству имен запрос на удаление соответствующей записи, и клиенты будут получать ложную информацию о доступности службы. Пример постоянного про- странства имен — NDS.
Перечень пространств имен
Теперь рассмотрим, как получить список доступных на компьютере про- странств имен. Большинство предопределенных пространств объявлены в заголовочном файле Nspapi.h. Каждому пространству имен присвоено цело- численное значение. Далее в списке перечислены некоторые распростра- ненные пространства имен, имеющиеся на платформах Win32:

2 8 8 ЧАСТЬ II Интерфейс прикладного программирования Wmsock
К NS_SAP — значение 1, пространс гво имен SAP, используемое в сетях IPX,
Ш NS_NDS — значение 2, пространство имен NDS, также используемое в сетях IPX,
Ш NS_DNS — значение 11, пространство имен DNS, широко используется в сетях TCP/IP и в Интернете,
Ш NS_NTDS — значение 32, пространство домена Windows NT, независимое от протокола, имеется в Windows 2000
Возвращаемый список пространств имен зависит от установленных на рабочей станции протоколов Например, если на ней не установлен прото- кол IPX/SPX, при перечислении пространств имен система не вернет NS_SAP
Установив в системе пакет протоколов IPX/SPX, вы сможете лишь выпол- нять запросы к пространству имен SAP Для регистрации собственных служб вам также потребуе гея служба SAP Agent В некоторых случаях для коррект- ного отображения адресов локального интерфейса IPX необходима служба
Client Services for NetWare — без нее адреса отображаются состоящими из нулей Кроме того, для работы с пространством имен NDS следует устано- вить клиент NDS Все указанные протоколы и службы можно установить при помощи Control Panel
Функция WSAEnumNameSpaceProviders API Wmsock 2 позволяет программ- но получить список доступных в системе пространств имен
INT WSAEnumNameSpaceProviders (
LPDWORD lpdwBufferLength,
LPWSANAMESPACE_INFO lpnspBuffer
),
Первый параметр — это размер буфера, ссылка на который передается в параметре lpnspBuffer Буфер обычно представляет собой достаточно большой массив структур WSANAMESPACEJNFO Если при вызове функции размер бу- фера окажется недостаточным, произойдет сбой, параметру lpdwBufferLength
будет присвоено значение, соответствующее минимально необходимому раз- меру буфера, и функция WSAGetLastError вернет WSAEFAULT При любой ошиб- ке функция возвращает SOCKETERROR или число возвращенных структур
WSANAMESPACEJNFO
Структура WSANAMESPACEJNFO описывает отдельное пространство имен,
заданное в системе
typedef struct _WSANAMESPACE_INFO {
GUID NSProviderld,
DWORD dwNameSpace,
BOOL fActive,
DWORD dwVersion,
LPTSTR lpszldentifier,
> WSANAMESPACE_INFO *PWSANAMESPACE_INFO,
LPWSANAMESPACE_INFO,
Фактически, существует два определения этой структуры — одно для
UNICODE и одно для ANSI Заголовочный файл Wmsock 2 выберет тип струк-

Г Л А В А 10 Регистрация и разрешение имен 289
туры WSANAMESPACEJNFO согласно способу сборки проекта Все структуры,
а также функции Winsock для регистрации и разрешения имен имеют как
ANSI-, так и UNICODE-версию Первый элемент структуры WSANAMESPACE_
INFO — NSPromderld Это глобально уникальный идентификатор (globally unique identifier, GUID), описывающий данное конкретное пространство имен Поле dwNameSpace — соответ ствующая пространству имен целочис- ленная константа например, NSJDNS или NS_SAP ЭлементJActive — логичес- кое значение, сообщающее о доступности пространства имен Если оно рав- но TRUE, пространство имен доступно и может принимать запросы Значе- ние, равное FALSE, указывает, что поставщик пространства имен простаива- ет и не может принимать запросы, ссылающиеся непосредственно на него
Поле dwVersion указывает версию этого поставщика Параметр Ipszldentifier —
это строковый идентификатор, описывающий данный поставщик
Регистрация службы
Следующий этап — создать собственную службу, а также предоставить све- дения о ней другим компьютерам сети и сделать ее доступной для них Этот процесс называется регистрацией экземпляра службы в компоненте досту- па к пространству имен После регистрации вы вправе рассылать информа- цию о службе, кроме того, клиенты, которым требуется взаимодействовать со службой, смогут выполнять к ней запросы Процесс регистрации службы включает два этапа Первый этап — определение класса службы (service class), описывающего ее характеристики
Важно различать класс службы и саму службу Класс службы описывает пространства имен, в которых будет зарегистрирована служба, а также ука- зывает определенные ее характеристики например, требует она установки логического соединения или нет Класс службы никак не описывает установ- ление соединения клиентом После регистрации класса службы можно за- регистрировать реальный экземпляр службы, ссылающийся на корректный класс службы, к которому он относится Затем клиенты с помощью запро- сов узнают, где выполняется ваш экземпляр службы, и устанавливают соеди- нение с ним
Определение класса службы
Регистрирует классы служб функция WSAInstallServiceClass из набора Winsock
INT WSAInstallServiceClass (LPWSASERVICECLASSINFO lpServiceClassInfo),
Единственный параметр — lpServiceClassInfo, указывает на структуру WSA-
SERVICECLASSINFO, определяющую атрибуты данного класса Синтаксис структуры выглядит следующим образом typedef struct _WSAServiceClassInfo {
LPGUID
LPTSTR
DWORD
LPWSANSCLASSINFO
lpServiceClassId,
lpszServiceClassName,
dwCount,
lpClassInfos,
> WSASERVICECLASSINFO, *PWSASERVICECLASSINFO, LPWSASERVICECLASSINFO,

2 9 0 ЧАСТЬ II Интерфейс прикладного программирования Winsock
Первое поле — GUID, уникально идентифицирующий данный конкрет- ный класс службы Создать GUID, используемый в этом определении, мож- но несколькими способами Прежде всего, при помощи утилиты Uuidgen exe,
но тогда для ссылки на этот GUID вам придется жестко задать его значение в каком-либо заголовочном файле Здесь на помощь приходит второе реше- ние В заголовочном файле Svcguid h несколько макросов создают GUID, на
S основе простого атрибута
Например, определяя класс службы для SAP, который будет применяться для рассылки информации об IPX-приложении, вы можете воспользовать-
, ся макросомSVCID^NETWARE Единственный параметр — идентификацион-
* ный номер SAP, присваиваемый классу приложений Число идентификато- ров SAP в NetWare предопределено 0x4 — для файловых серверов, 0x7 — для серверов печати и т д В этом случае необходим лишь легко запоминаемый идентификатор SAP, на основе которого создается GUID для соответствую- щего класса службы Кроме того, существует несколько макросов, принимаю- щих в качестве параметра номер порта, и возвращающих GUID соответству- ющей службы
Рассмотрим заголовочный файл Svcguid h, содержащий полезные макро- сы для выполнения обратной операции — получения номера порта службы по ее GUID Перечислим наиболее часто используемые макросы для созда- ния GUID на основе простых атрибутов протоколов, таких как номера пор- тов или идентификаторы SAP Эти макросы генерируют GUID, используя
SVCID TCP (Port) — номер порта протокола TCP,
Ш SVCIDDNS(RecordType) — тип записи DNS,
К SVCID_UDP'(Port) — номер порта протокола UDP,
Ш SVCIDNETWARE (Sapid) идентификатор SAP
В заголовочном файле также есть константы для распространенных но- меров портов, используемых службами типа FTP и Telnet
Второе поле структуры WSASERVICECLASSINFO ipszServtceClassName, стро- ка с именем данного конкретного класса службы Два последних элемента взаимосвязаны Поле dwCount ссылается на число структур WSANSCLASSINFO,
переданное в поле IpClassInfos Эти структуры определяют пространства имен и характеристики протоколов, которые распространятся на регистрирую- щиеся в данном классе службы Структура WSANSCLASSINFO определена так
typedef struct _WSANSClassInfo {
^ LPSTR lpszName,
DWORD dwNameSpace,
\ DWORD dwValueType,
DWORD dwValueSize,
LPVOID lpValue,
>WSANSCLASSINFO, *PWSANSCLASSINFO, *LPWSANSCLASSINFO,
Поле lpszName определяет атрибут, принадлежащий классу службы В
табл 10-1 перечислены возможные атрибуты, а также пространства имен, к которым обычно относятся различные типы служб Тип значения всех ука-

Г Л А В А 10 Регистрация и разрешение имен
291
занных атрибутов — REG DWORD Параметр dwNameSpace — пространство имен, на которое распространяется данный атрибут
Табл 10-1. Классы служб
Строковое
значение
Sapid
Connection-
Oriented
TcpPort
UdpPort
Константа определяет
SERVICE_TYPE_VALUEJAP1D
SERVICE_TYPE_VALUE_CONN
SERVICE TYPE VALUE
TCPPORT
SERVICE ТУРЕ VALUE
UDPPORT
Пространство
имен
NS_SAP
Любое
NS
DNS
NSJVTDS
NS
DNS
NS_NTDS
Описание
Идентификатор SAP
Указывает, требует ли служба установления соединения
Порт TCP
Порт UDP
Последние три поля — dwValueType, dwValueSize и IpValue, описывают ре- альное значение, связанное с типом службы Поле dwValueType указывает тип данных, связанный с этой записью, и может принимать одно из значений,
используемых в реестре Например, если значение равно DWORD, его тип —
REGDWORD Следующее поле — dwValueSize, содержит размер данных, пе- реданных в параметре IpValue, представляющем собой указатель на данные
Приведенный далее код определяет класс службы Widget Server Class
WSASERVICECLASSINFO sci,
WSANSCLASSINFO
DWORD
int
aNameSpaceClassInfo[4];
dwSapId = 200,
dwUdpPort = 5150,
dwZero = 0;
ret;
memset(&sci, 0, sizeof(sci)),
SET_NETWARE_SVCID(&sci.lpServiceClassId, dwSapId);
sci.lpszServiceClassName = (LPSTR)'Widget Server Class"
soi dwCount = 4,
sci lpClassInfos = aNameSpaceClassInfo;
4);
memset(aNameSpaceClassInfo, 0, sizeof(WSANSCLASSINFO)
// Настройка пространства имен NTOS
aNameSpaceClassInfo[0] lpszName = SERVICE_TYPE_VALUE_CONN;
aNameSpaceClassInfo[0].dwNameSpace = NS.NTDS;
aNameSpaceClassInfo[0] dwValueType = REG_DWORD;
aNameSpaceClassInfo[0].dwValueSize = sizeof(DWORD);
aNameSpaceClassInfo[0] lpValue = &dwZero;
aNameSpaceClassInfo[1].lpszName = SERVICE_TYPE_VALUE_UDPPORT;
aNameSpaceClassInfo[1] dwNameSpace = NS.NTDS,
aNameSpaceClassInfo[1] dwValueType = REG_DWORD;
aNameSpaceClassInfo[1] dwValueSize = sizeof(DWORD);
aHameSpaceClass!nfo[1].IpValue = &dwUdpPort;

2 9 2 Ч А С Т Ь II Интерфейс прикладного программирования Winsock
// Настройка пространства имен SAP
aNameSpaceClassInfo[2].lpszName = SERVICE_TYPE_VALUE_CONN;
aNameSpaceClassInfo[2].dwNameSpace = NS_SAP;
aNameSpaceClassInfo[2].dwValueType = REG_DW0RD;
aNameSpaceClassInfo[2].dwValueSize = sizeof(DWORD);
aNameSpaceClassInfo[2].lpValue = &dwZero;
aNameSpaceClassInfo[3].lpszName = SERVICE_TYPE_VALUE_SAPID; ,
aNameSpaceClassInfo[3].dwNameSpace = NS.SAP;
aNameSpaceClassInfo[3].dwValueType = REG_0W0RD;
aNameSpaceClassInfo[3].dwValueSize = sizeof(DWORD);
aNameSpaceClassInfo[3].lpValue = idwSapId;
ret = WSAInstallServiceClass(&sci);
if (ret == SOCKET.ERROR)
printf("WSAInstallServiceClass() failed Xd\n", WSAGetLastErrorO);
Сначала выбирается GUID, под которым будет зарегистрирован класс. Все создаваемые службы относятся к классу Widget Server Class, описывающему общие атрибуты, которыми обладает экземпляр службы. В примере регист- рируется класс службы с идентификатором NetWare SAP, равным 200. Это сделано лишь для удобства — мы могли бы выбрать произвольный GUID или даже GUID, основанный на номере порта UDP. Кроме того, служба может работать по протоколу UDP, который в нашем примере клиенты прослуши- вают на порте номер 5150.
Затем полю dwCount структуры WSASERVICECIASSINFO присваивается значе- ние 4. В этом примере класс службы регистрируется и в пространстве имен SAP
(NS_SAP), и в пространстве домена Windows NT (NS_NTDS). Обратите внимание:
используются четыре структуры WSANSCLASSINFO, хотя класс регистрируется лишь в двух пространствах имен. Это связано с тем, что для каждого простран- ства имен определены два атрибута, которым необходимы отдельные структу- ры WSANSCLASSINFO. Мы также указываем, требует ли пространство имен уста- новления логического соединения. В этом примере логическое соединение не нужно, поскольку мы присвоили полю SERVICE_TYPEyALUE_CONN логическое значение 0. Кроме того, для пространства домена Windows NT указан тип служ- бы SERVICE_TYPE_VALUE_UDPPORT'и номер порта UDP, на котором обычно вы- полняется эта служба. Для пространства имен SAP идентификатор SAP задает- ся с использованием типа службы SERVICE_TYPE_VALUE_SAPID.
Для каждой записи WSANSCLASSINFO необходимо определить идентифи- катор пространства имен, к которому относится данный тип службы; кро- ме того, следует задать тип и размер значения (табл. 10-1). В нашем приме- ре все значения оказались DWORD. На последнем этапе вызывается функция
WSAInstallServiceClass и ей в качестве параметра передается структура WSASER-
VICECIASSINFO. При успешном вызове функция вернет 0, в противном слу- чае — SOCKET_ERROR. Если структура WSASERVICECIASSINFO не действитель- на или некорректно сформирована, функция WSAGetLastError вернет WSAEIN-

Г Л А В А 10 Регистрация и разрешение имен 293
VAL. При наличии такого же класса службы функция вернет WSAEALREADY. В
нашем случае для удаления класса службы можно вызвать функцию WSAEAL-
READY:
INT WSARemoveServiceClass( LPGUID lpServiceClassId );
Единственный параметр функции — указатель на GUID, который опреде- ляет класс службы.
Регистрация службы
После определения класса службы, описывающего ее общие атрибуты, мож- но зарегистрировать экземпляр службы и сделать ее доступной для других клиентов. Для регистрации службы применяется функция WSASetService из набора Winsock:
INT WSASetService (
LPWSAQUERYSET lpqsReglnfo,
WSAESETSERVICEOP essOperation,
DWORD dwControlFlags
);
Первый параметр — lpqsReglnfo, указатель на структуру WSAQUERYSET, оп- ределяющую конкретную службу. Параметр essOperation определяет выпол- няемое действие — регистрацию или удаление сведений о службе. Вот опи- сание трех допустимых флагов.
Ш RNRSERVICE REGISTER — регистрирует службу Для поставщиков дина- мических имен это означает начало активной рассылки информации о службе, для поставщиков постоянных имен — обновление БД, для постав- щиков статичных имен — ничего.
Ш RNRSERVICE DEREGISTER — удаляет все сведения о службе из реестра.
Для поставщиков динамических имен это означает прекращение рассыл- ки информации о службе, для поставщиков постоянных имен — удаление сведений о службе из БД, для поставщиков статичных имен — ничего.
Ш RNRSERMCEDELETE — удаляет данный экземпляр службы из простран- ства имен. Служба, которую можно зарегистрировать, содержит несколь- ко экземпляров (если при регистрации задан флаг SERVICE_MULTIPLE), и данная команда удаляет лишь выбранный экземпляр службы (определя- ется структурой CSADDRJNFG). Все сказанное также распространяется на поставщиков динамических и постоянных имен.
Третий параметр — dwControlFlags, равен 0 или флагу SERVICE_MULTIPLE.
Этот флаг используется, если данный экземпляр службы регистрируется с несколькими адресами. Например, требуется запустить службу на пяти сис- темах. Структура WSAQUERYSET, переданная функции WSASetService, будет ссылаться на пять структур CSADDRJNFO, каждая из которых описывает раз- мещение одного из экземпляров службы. Для этого необходимо задать флаг
RNRSERVICE DELETE. В табл. 10-2 приведены возможные комбинации управ-

294
1   ...   22   23   24   25   26   27   28   29   ...   50


написать администратору сайта