Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Программирование в сетях Windows

.pdf
Скачиваний:
538
Добавлен:
11.03.2015
Размер:
3.02 Mб
Скачать

148

ЧАСТЬ II Интерфейс прикладного программирования Winsock

NBPJTUPLE, так как возвращаемые в результате поиска имени данные — массив структур WSH_NBP_TUPLE. Зная начальное положение и тип записей, мы можем просмотреть весь массив. Подробнее о параметрах сокетов — в главе 9.

Создание сокета

Для создания сокета можно использовать любую подходящую функцию Winsock, начиная с версии 1.1. Существует два способа задать базовые протоколы AppleTalk: использовать определение соответствующего протокола из файла Atalkwshh, либо вызвать функцию WSAEnumProtocols и поместить результаты в структуру WSAPROTOCOLJNFO. В табл. 6-1 для каждого протокола AppleTalk приведены параметры, необходимые для создания сокета функциями socket или WSASocket.

Табл. 6-1. Протоколы и параметры AppleTalk, семейство адресов

AFAPPLETALK

Протокол

Тип сокета

Тип протокола

MSAFD AppleTalk [ADSP]

SOCK_RDM

ATPROTOADSP

MSAFD AppleTalk [ADSP] [псевдопоток]

SOCKSTREAM

ATPROTO_ADSP

MSAFD AppleTalk [PAP]

SOCKRDM

ATPROTOPAP

MSAFD AppleTalk [RTMP]

SOCKJXRAM

DDPPROTO_RTMP

MSAFD AppleTalk [ZIP]

SOCKDGRAM

DDPPROTO ЛР

ПротоколATM

Winsock 2 в Windows 98 и Windows 2000 поддерживает протокол Asynchronous Transfer Mode (ATM), применяемый как в локальных, так и в глобальных сетях для высокоскоростной передачи данных любого типа (в том числе звуковой и видеоинформации). Протокол ATM гарантирует качество обслуживания (quality of service, QoS) за счет виртуальных соединений (Virtual Connections, VC) в сети. Для установления виртуальных соединений в сети ATM Winsock использует семейство адресов ATM. Типичная сеть ATM состоит из конечных точек (компьютеров), соединенных коммутаторами (рис. 6-1).

При программировании протокола ATM необходимо учитывать несколько особенностей. Во-первых, ATM — это фактически не протокол, а тип носителя. Иными словами, технология ATM напоминает запись кадров Ethernet прямо в сеть Ethernet. Как и Ethernet, сеть ATM не способна управлять потоками (flow control). Протокол ATM предварительно устанавливает соединение и работает в режимах сообщений или потоков. Это означает, что если отправка данных замедлится, исходное приложение может переполнить локальный буфер. Аналогично, если приложение-получатель не будет считывать данные достаточно часто, произойдет переполнение буфера на стороне получателя и часть принятой информации будет утеряна. Для управления потоками вы вправе использовать протокол IP поверх ATM. В этом случае приложения будут работать с семейством IP-адресов. Хотя протокол ATM обладает определенными преимуществами по сравнению с IP — например,

Г Л А ВА 6 Семейства адресов и разрешение имен

i 149

допускает корневую многоадресную схему (см. главу 12) — при выборе протокола нужно учитывать специфику приложения.

Коммутатор ATM

а

Конечные Конечные точки ATM точки ATM

Коммутатор ATM

Рис. 6-1. Сеть ATM

ПРИМЕЧАНИЕ Так как поддержка ATM — новинка Winsock 2, информация из этого раздела протестирована только на реализации ATM для Windows 2000 Beta 3. Windows 98 (SP 1) не была доступна для тестирования ко времени написания этой книги. Поэтому содержащееся здесь описание протокола ATM может несколько отличаться от его окончательной реализации в Windows 2000 и Windows 98 (SP 1).

Адресация

В сети ATM два сетевых интерфейса: «пользователь сеть* (user network interface, UNI) и «узел сеть» (network node interface, NNI). Первый определяет взаимодействие компьютеров и коммутаторов ATM, второй — взаимодействие двух коммутаторов. У каждого из этих интерфейсов есть соответствующий протокол.

Сигнальный протокол UNI позволяет компьютеру и коммутатору ATM обмениваться информацией об установлении соединения и управляющей информацией, обеспечивая установку соединения в сети ATM. При использовании этого протокола компьютер может общаться только с ближайшим коммутатором, через несколько коммутаторов данные не передаются.

Сигнальный протокол NNI позволяет двум коммутаторам обмениваться информацией о маршрутизации и управляющей информацией.

Здесь описаны только те элементы сигнального протокола UNI, которые касаются установки соединения ATM средствами Winsock. В настоящее время Winsock в Windows 2000 и Windows 98 (SP 1) поддерживает сигнальный протокол UNI версии 3.1.

150

ЧАСТЬ II Интерфейс прикладного программирования Winsock

Для обмена данными по сети ATM с помощью сигнального протокола UNI, Winsock использует механизм точек доступа к службам (Service Access Point, SAP). Напомним, что для обмена данными через сеть ATM между компьютерами должно быть предварительно установлено виртуальное соединение. SAP позволяет приложениям Winsock зарегистрировать и идентифицировать интерфейс сокета для связи по сети ATM с помощью адресной структуры SOCKADDR_ATM. Создав SAP, Winsock устанавливает виртуальное соединение между клиентом и сервером (используя сигнальный протокол UNI). Структура SOCKADDR_ATM определена так:

typedef struct sockaddr_atm

u_short satm_family; ATM.ADDRESS satm..number;

ATM.BLLI satm..blli; ATM.BHLI satm..bhli;

ckacidr atm, SOCKADDRATM, «PSOCKADDRATM, •LPSOCKADDRATM;

Поле satmjamily всегда должно быть равноAF_ATM. Поле satmjiumber — фактический адрес ATM в виде структуры ATM_ADDRESS. Он основан на одной из двух основных схем адресации ATM: E.I64, либо точках доступа к сетевым службам (Network Service Access Point, NSAP). Адреса NSAP также называют системными адресами ATM в стиле NSAP (NSAP-style ATM Endsystem Address, AESA). Структура SOCKADDR_ATM определена так:

typedef struct

{

DWORD AddressType;

DWORD NumofDigits;

UCHAR Addr[ATM_ADDR_SIZE];

}ATM.ADDRESS;

Вполе AddressType задается схема адресации: для ЕЛ64 значение поля должно быть АТМ_Е1б4, для NSAP — ATM_NSAP. Кроме того, если приложение пытается осуществить привязку сокета к SAP, то этому полю можно присвоить и другие значения:

КАТМЕ164 — адрес ЕЛ 64, применяется при соединении с SAP;

ШATMNSAP — адрес в стиле NSAP, применяется при соединении с SAP;

ШSAPFIELDANYAESASEL — адрес в стиле NSAP с параметризованным

селекторным октетом, служит для привязки сокета к SAP;

SAPFIELDANYAESAREST — адрес в стиле NSAP со всеми октетами, кроме параметризованного, служит для привязки сокета к SAP.

Поле NumofDigits всегда должно быть равно ATM_ADDR SIZE. В поле. Addr

содержится фактический 20-байтный адрес ATM по схеме ЕЛ 64 или NSAR Поля satm_blli и satmbhli структуры SOCKADDR_ATM в ATM UNI пред-

ставляют широкополосную информацию нижнего (Broadband Lower Layer Information, BLLI) и верхнего уровня (Broadband Higher Layer Information,

Г Л А ВА 6 Семейства адресов и разрешение имен

(151

BHLI) соответственно. Вообще, эти структуры используются для идентификации стека протокола, работающего поверх соединения ATM. В документах по ATM Form/IETF описано несколько стандартных комбинаций значений BHLI и BLLI. (Одна комбинация идентифицирует соединение по ATM с эмуляцией ЛВС, другая — IP поверх ATM и т. п.) Полные диапазоны значений для полей этих структур приведены в книге стандартов ATM UNI 3.1, а документы по ATM Form/IETF можно найти по адресу http://www.ietf.org.

Структуры данных BHLI и BLLI определены так:

typedef struct

{

DWORD HighLayerlnfoType;

DWORD HighLayerlnfoLength; UCHAR HighLayerInfo[8];

} ATM_BHLI;

typedef struct

{

DWORD Layer2Protocol;

DWORD Layer2UserSpecifiedProtocol; DWORD Layer3Protocol;

DWORD Layer3UserSpecifiedProtocol; DWORD Layer3IPI;

UCHAR SnapID[5]; } ATMJ3LLI;

Подробности определения и использования этих полей выходят за рамки нашей книги. Для связи по сети ATM средствами Winsock приложению необходимо присвоить значение SAP_FIELD_ABSENT следующим полям структур BHLI и BLLI:

ШATMВШ Layer2Protocol;

ШАТМВШ Layer3Protocol;

ATM BH11 HighLayerlnfoType.

Когда эти поля получают значение SAP_FIELD_ABSENT, другие поля обеих структур не используются. Вот пример, иллюстрирующий возможное применение структуры SOCKADDR_ATM для настройки SAP под адрес NSAP:

SOCKADDR.ATM atm_addr;

UCHAR MyAddress[ATM_ADDR_SIZE];

atm_addr.satm_family

= AF_ATM;

atm_addr.satm_number.AddressType

= ATM_NSAP;

atm-addr.satm_number.NumofDigits

= ATM_ADDR_SIZE;

atm_addr.satiti_blli.Layer2Protocol

= SAP_FIELD_ABSENT;

atm_addr.satm_blli.Layer3Protocol

= SAP_FIEID_ABSENT;

tm-addr.satm_bhli.HighLayerlnfoType

= SAP_FIELD_ABSENT;

memcpy(&atm_addr.satm_number.Addr, MyAddress, ATM_ADDR_SIZE);

1 52

ЧАСТЬ II Интерфейс прикладного программирования Winsock

ATM-адрес, как правило, представляет собой шестнадцатеричную ASCIIстроку из 40 символов, которая соответствует 20 байтам, составляющим адрес в стиле NSAP или Е 164 в структуре ATM ADDRESS Например, адрес ATM в стиле NSAP мог бы выглядеть так

47000580FFE1000000F21A1D540000D10FED5800

Преобразование этой строки в 20-байтный адрес может занять довольно много времени, однако Winsock предоставляет независимую от протокола функцию — WSAStrtngToAddress, позволяющую преобразовывать 40-сим- вольную шестнадцатеричную строку ASCII в структуру ATMADDRESS (Эта функция подробно описана в конце главы ) Другой способ преобразовать шестнадцатеричную строку ASCII в шестнадцатеричный (двоичный) формат — использовать функцию AtoH (листинг 6-2) Эта функция не входит в

Winsock, но разработать ее просто (см

примеры в главе 7)

Листинг 6-2. Функции, преобразующие шестнадцатеричные строки ATM

//

 

 

 

 

 

// Функция

AtoH

 

 

 

 

//

 

 

 

 

 

// Описание

Эта функция преобразует ATM-адрес из строкового

// формата(ASCII) в двоичный (шестнадцатеричный)

//

 

 

 

 

 

void AtoH(CHAR *szDest,

CHAR

«szSource, INT iCount)

{

 

 

 

 

 

while (iCount-)

 

 

 

 

{

 

 

 

 

 

*szDest++ =

(

BtoH (

*szSource++ )

« 4 )

 

+ BtoH (

*szSource++ );

 

}

 

 

 

 

 

return;

>

//

// Функция. BtoH

//

//Описание: Эта функция возвращает эквивалентное двоичное значение

//для отдельного символа в формате ASCII

//

UCHAR BtoH( CHAR ch )

{

if ( ch >= '0' && ch <= '91 )

{

return ( ch - '0' );

}

if ( ch >= 'A1 && ch <= 'Ff )

{

 

return ( ch - 'A' + OxA );

 

 

,

u

* *•'

 

. ГЛАВА 6 Семейства адресов и разрешение имен

' 153

Листинг 6-2.

(продолжение)

 

if (ch >=

'a' && ch <= T )

 

return ( ch - 'а1 + ОхА ),

// Неверные значения при указании адреса не принимаются

return -1;

Создание сокета

В ATM приложения могут создавать только ориентированные на соединение сокеты, поскольку ATM позволяет связываться только по VC Поэтому данные могут быть переданы или как поток байт, или как отдельное сообщение Для открытия АТМ-сокета вызовите функцию socket или WSASocket с семейством адресов AF_ATM и типом сокета SOCK_RAW, а полю протокола присвойте

ATMPROTO_AAL5-

s = socket(AF_ATM, S0CK_RAW, ATMPR0T0_AAL5),

s = WSASocket(AF_ATM, SOCK_RAW, ATMPR0T0_AAL5, NULL, 0, WSA_FLAG_OVERLAPPED),

По умолчанию при открытии сокета (как в примере) создается потоковый сокет ATM Windows также выводит сведения о поставщике ATM, способном передавать данные в виде сообщений Чтобы его использовать, явно определите поставщик исходного ATM-протокола для функции WSASocket при помощи структуры WSAPROTOCOLJNFO (см главу 5) Это необходимо, так как в Winsock в запросах socket и WSASOCKET каждому поставщику ATM соответствуют три элемента семейство адресов, тип сокета и протокол По умолчанию, Winsock возвращает стандартную запись протокола, соответствующую всем трем атрибутам, в нашем случае — это поставщик для потоковой передачи данных Следующий пример показывает, как найти поставщика ATM, передающего данные в виде сообщений, и открыть сокет

dwRet = WSAEnumProtocols(NULL, lpProtocolBuf, idwBufLen),

for ( i = 0 , i < dwRet, i++)

if ((lpProtocolBuf[i].iAddressFamily == AF.ATM) && dpProtocolBuf[i] iSocketType == S0CK_RAW) && dpProtocolBuf[i] iProtocol == ATMPR0T0_AAL5) && dpProtocolBuf[i] dwServiceFlagsi &

XP1JIESSAGE_0RIENTED))

s

= WSASocket(FR0M_PR0T0C0L_INF0, FROM_PROTOCOL_INFO,

 

FROM_PROTOCOL_INFO, lpProtocolBuf[i], 0,

 

WSA_FLAG_OVERLAPPED);

у

l>,.RHM5Rf«M

1 54

ЧАСТЬ II Интерфейс прикладного программирования Wmsock

Привязка сокета к SAP

Адреса ATM довольно сложны, так как в 20 байтах адреса содержится много информационных элементов. Из них внимания программистов Winsock заслуживает лишь последний байт. Последний байт адреса в стиле NSAP или Е.164 соответствует номеру селектора, который уникальным образом позволяет приложению распознать и определить SAP на конечной точке. Как мы уже говорили, Winsock использует SAP для связи по сети ATM.

Приложение-сервер должно зарегистрировать SAP на конечной точке и дождаться, пока приложение-клиент соединится по зарегистрированному SAP. Для клиента это означает лишь настройку структуры SOCKADDR_ATM с типом адреса ATM_Е164 или ATM_NSAP и предоставление адреса ATM, связанного с SAP сервера. Для создания SAP и ожидания соединений приложение должно сначала создать сокет для семейства адресов AF_ATM. Затем необходимо определить структуру SOCKADDRATM, используя такие типы адреса, как

SAP_FIELD_ANY_AESA_SEL,SAP_FIELD_ANY_AESA_REST,ATM_El64илиАТМ_№АР

(см. список значений поля AddressType в разделе «Протокол ATM Адресация»). Для АТМ-сокета SAP создается при вызове приложением функции bind (см. главу 7), а типы адреса определяют способ создания SAP на вашей конечной точке.

Тип адреса SAPJFIELD_ANY_AESA_SEL позволяет создать SAP для прослушивания любого входящего соединения ATM (параметризация адреса ATM и селектора). Это значит, что только один сокет может быть привязан к этой конечной точке для прослушивания любых соединений: при попытке соединения другого сокета с этим типом адреса выдается ошибка WSAEADDRINUSE. Впрочем, вы можете явно сопоставить дополнительные сокеты конечной точкедляконкретногоселектора.ПрименяятипадресаSAP_FIELD_ANY_AESA_REST, можно создать SAP, явно привязанную к указанному селектору конечной точки (параметризация адреса ATM без селектора). Нельзя одновременно использовать более одного сокета, привязанного к конкретному селектору на конечной точке, иначе вызов bind вернет ошибку WSAEADDRINUSE. Для типа

SAP_FIELD_ANY_AESA_SEL в структуре ATM_ADDRESS задайте ATM-адрес из нулей, для типа SAP_FIELD_ANY_AESAJREST — обнулите первые 19 байт АТМадреса. Последний байт должен указывать номер требуемого селектора.

Сокеты,связанныесконкретнымиселекторами(SAP_FIELD_ANY_AESA_REST), приоритетнее связанных с параметризованными селекторами (SAP_FIELD_ ANY_AESA_SEL). А потому первыми при соединениях будут выбраны или они, или сокеты, связанные с явными интерфейсами — ATM_NSAP и АТМЕ164- (Если у конечной точки запрошено входящее соединение с указанием явно слушаемого селектора, сокет принимает соединение.) Подключение к сокету с указанием параметризованного селектора произойдет только в отсутствие доступных сокетов, связанных с конкретными селекторами. Создание сокета, прослушивающего соединения по SAP, описано в главе 7.

Наконец, служебная программа Atmadm.exe позволяет получить всю информацию об ATM-адресе и виртуальном соединении на конечной точке. Это может пригодиться при разработке приложения ATM, когда понадобится

Г Л А ВА 6 Семейства адресов и разрешение имен

i 155

информация о доступных на конечной точке интерфейсах. Вот параметры командной строки это программы:

щ перечисляет все соединения (VC), удаленный адрес и локальный интерфейс;

ш_а — перечисляет все зарегистрированные адреса (все локальные интерфейсы ATM и их адреса);

щ_s — выводит статистику: текущее число запросов, количество принятых

иотправленных сигнальных пакетов и ILMI-пакетов и т. п.

Разрешение имен

В настоящее время для ATM под Winsock нет доступных поставщиков имен. Поэтому, к сожалению, требуется задавать 20-байтный адрес ATM для сокетной связи по сети ATM. В главе 10 рассматривается DNS-пространство Windows 2000, в котором можно регистрировать ATM-адреса с дружественными именами служб.

ДополнительныефункцииWinsock2

Функции WSAAddressToString и WSAStringToAddress в Winsock 2 обеспечивают независимый от протокола способ преобразования структуры SOCKADDR протокола в форматированную строку символов и наоборот. Так как эти функции не зависят от протокола, транспортный протокол должен поддерживать преобразование строк. В настоящее время эти функции работают только для семейств адресов AFJNET и AF_ATM. Функция WSAAddressToString определена так:

INT WSAAddressToString( LPSOCKADDR lpsaAddress, DWORDdwAddressLength,

LPWSAPROTOCOL_INFO lpProtocolInfo, OUT LPTSTR lpszAddressString,

IN OUT LPDWORD lpdwAddressStringLength

);

Параметр lpsaAddress соответствует структуре SOCKADDR для конкретного протокола, содержащего адрес, который надо преобразовать в строку. Параметр dwAddressLength задает размер структуры первого параметра для каждого протокола. Необязательный параметр lpProtocolInfo представляет поставщик протокола. Поставщиков протокола можно найти функцией WSAEnumProtocols (см. главу 5). Если вы зададите NULL, вызов использует поставщик первого протокола, поддерживающего семейство адресов из lpsaAddress. Параметр lpszAddressString — буфер, где сохраняется удобная для чтения адресная строка. Параметр lpdwAddressStringLength — это размер ipszAddres- s tring. При выводе в нем возвращается длина строки, фактически скопированной в lpszAddressString. Если предоставленный буфер мал, функция выда-

ет о щ и б к у WSAEFAULT, а в параметре lpdwAddressStringLength вернется требуемый размер в байтах.

156

ЧАСТЬ II Интерфейс прикладного программирования Winsock

Функция WSAStringToAddress, напротив, преобразует удобную для чтения адресную строку в структуру SOCKADDR:

INT WSAStringToAddress( LPTSTR AddressString, INT AddressFamily,

LPWSAPR0T0C0L_INF0 lpProtocolInfo, LPSOCKADDR lpAddress,

LPINT lpAddressLength

);

В параметре AddressString передается адресная строка, формат которой для поддерживаемых протоколов:

Я для IP — XXXXXXXXXXXXY, где X представляет октет в строке IP-адре- са, а У — номер порта;

Ш для ATM - NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN,

где 40 символов N представляют 20-байтный ATM-адрес в шестнадцатеричном формате.

Параметр AddressFamily представляет тип семейства адресов для параметра AddressString. Необязательный параметр lpProtocolInfo представляет поставщик протокола. Если вы присвоите ему NULL, Winsock будет искать первый доступный поставщик протокола для типа адресного семейства из AddressFamily. Для выбора конкретного поставщика получите с помощью WSAEnumProtocols список доступных поставщиков протокола, установленных на вашей системе. В параметре lpAddress хранится структура SOCKADDR, принимающая информацию в адресной строке. Параметр lpAddressLength представляет размер результирующей структуры SOCKADDR.

Резюме

Мы описали семейства адресов протоколов, поддерживаемых Winsock, и пояснили специфичные атрибуты адресации. Для каждого семейства адресов были подробно рассмотрены создание сокета и настройка структуры адреса сокета для организации связи по протоколу.

В следующей главе обсуждаются основные методики связи в Winsock, применимые ко всем семействам адресов, рассмотренным в этой главе.

XI.

Г Л А В А

Основы Winsock

Эта глава посвящена изучению основных методик и API-вызовов, необходимых для написания сетевых приложений. Из материалов предыдущей главы вы знаете, как протоколы, доступные из Winsock, адресуют компьютеры и службы. Здесь мы рассмотрим способы установления соединения между двумя компьютерами в сети и механизмы обмена данными. Во избежание повторов, мы обсудим лишь протокол TCP/IP. На прилагаемом компакт-диске содержатся примеры клиент-серверных приложений для каждого из рассмотренных в главе б протоколов. Единственная зависящая от протокола операция — это создание сокета. Большинство остальных вызовов функций Winsock, ответственных за установление соединения, отправку и прием данных, не зависят от протокола. Все исключения упоминались в главе 6 при обсуждении конкретных протоколов.

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

Кроме того, будут представлены разновидности API-функций для версий Winsock 1 и 2. Если в спецификации Winsock 2 обновлена или добавлена новая API-функция, то ее имя начинается с префикса WSA. Например, имя функции Winsock 1, создающей сокет — socket. В Winsock 2 есть ее новая версия — WASSocket, использующая расширенные возможности Winsock 2. Исключения из этого правила: функции WSAStartup, WSACleanup, WSARecvEx и WSAGetLastError, — упоминаются уже в спецификации Winsock 1.1.

ИнициализацияWinsock

Любое Winsock-приложение перед вызовом функции должно загрузить соответствующую версию библиотеки Winsock. Если этого не сделать, функция вернет значение SOCKET_ERROR и выдаст ошибку WSANOTINITIAUSED. Загрузку библиотеки Winsock выполняет функция WSAStartup:

int WSAStartup(

WORD wVersionRequested, LPWSADATA lpWSAData