Программирование в сетях Windows. Э. Джонс, Д. Оланд
Скачать 2.88 Mb.
|
Адресация Имя AppleTalk фактически основано на трех отдельных именах: собственно имени, типе и зоне. Длина каждого из этих имен не может быть больше 32 символов. Имя идентифицирует процесс и связанный с ним сокет на ком- пьютере. Тип — это механизм группировки для зон. Обычно зона представ- ляет собой сеть компьютеров, поддерживающих AppleTalk и расположенных в одной петле (loop). Реализация протокола AppleTalk от Microsoft позволяет компьютеру под управлением Windows указать зону, в которой он находит- ся. Несколько сетей можно соединить мостами. Номеру сокета, узла и сети соответствуют дружественные имена. Протокол Name Binding Protocol (NBP) требует, чтобы имя AppleTalk было уникальным для данного типа и зоны Для проверки уникальности имени этот протокол применяет широковещатель- ные запросы. Чтобы динамически определить маршруты к соединенным сетям, AppleTalk использует Routing Table Maintenance Protocol (RTMP). В основе адресации узлов AppleTalk из Winsock лежит структура: typedef struct sockaddr_at { USHORT sat_family; USHORT sat.net; UCHAR sat_node; UCHAR sat_socket; } SOCKADDR_AT, *PSOCKADDR_AT; Заметьте: эта структура содержит только символы и короткие целые чис- ла, но не дружественные имена. Структура SOCKADDR_ATпередается в таких функциях Winsock, как bind, connect и WSAConnect, однако для трансляции Г Л А В А 6 Семейства адресов и разрешение имен ,141 пужественного имени необходимо сначала разрешить или зарегистриро- ть это имя функциями getsockopt и setsockopt соответственно. Регистрация имени AppleTalk Зарегистрировать сервер под определенным именем, которое будут использо- вать клиенты, позволяет функция setsockopt с параметром SO_REGISTER_NAME. Пдя всех параметров сокетов, связанных с именами AppleTalk, используйте структуру WSH_NBP_NAME: typedef struct CHAR ObjectNameLen; CHAR ObjectName[MAX_ENTITY]; CHAR TypeNameLen; CHAR TypeName[MAX_ENTITY]; CHAR ZoneNameLen; CHAR ZoneName[MAX_ENTITY]; } WSH_NBP_NAME, «PWSH_NBP_NAME; Ряд типов: например, WSH_REGISTER_NAME, WSH_DEREG1STER_NAME и WSH_REMOVE_NAME, — определены на основе структуры WSH_NBP_NAME. Выбор типа зависит от того, ищете ли вы имя, регистрируйтесь под ним, или удаляете его. Вот как зарегистрировать имя AppleTalk: «define «define «define MY_ZONE MY_TYPE MY_0BJECT WSH_REGISTER_NAME SOCKADDF SOCKET i_AT "Winsock-Test-App" "AppleTalk-Server" atname; ataddr; s; // Впишите регистрируемое имя // strcpy(atname.ObjectName, MY.OBJECT); atname.ObjectNameLen = strlen(MY_OBJECT); strcpy(atname.TypeName, MY_TYPE); atname.TypeNameLen = strlen(MY TYPE); strcpy(atname.ZoneName, MY_Z0NI); atname.ZoneNameLen = strlen(MY_ZONE); s = socket(AF_APPLETALK, SOCK.STREAM, ATPROTOJUWP&b< i, if (s == INVALID_SOCKET) // Ошибка ataddr.sat^socket = О- a ? a t - f a m i l y = A F (s, (SOCKADDR .)&ataddr, sizeof(at*Alie5/r« SOCKET.ERROR) 142 ЧАСТЬ II Интерфейс прикладного программирования Wmsock // Невозможно открыть конечную точку в сети AppleTalk } if (setsockopt(s, SOL_APPLETALK, SO_REGISTER_NAHE, (char O&atname, sizeof(WSH_NBP_NAME)) == SOCKET_ERROR) { // Ошибка при регистрации имени 1 Первое, на что следует обратить внимание, — строки MYZONE, MYJTYPE YL MY OBJECT Как вы помните, имя AppleTalk трехуровневое В рассматривае- мом примере вместо имени зоны стоит звездочка (*) Она обозначает теку- щую зону, то есть зону, в которой находится ваш компьютер Затем создает- ся сокет с типом SOCK_STREAM и вызывается функция bind со структурой адреса, где значение поля sat socket обнулено и только полю семейства про- токолов присвоено значение Это важно, поскольку в результате в сети Apple- Talk создается конечная точка, откуда ваше приложение сможет выполнять запросы Хотя вызов функции bind и позволяет выполнять простейшие опе- рации в сети, сам по себе он не дает возможности приложению принимать входящие клиентские запросы Для этого необходимо сделать следующий шаг — зарегистрировать имя в сети Сделать это не так уж сложно вызовите функцию setsockopt, передав в нее в качестве параметра level SOL_APPLETALK, а в качестве параметра optname — SO_REGISTER_NAME Эти параметры — указатели на структуру WSHJREGIS- TERJSIAME и ее размер Успешный вызов данной функции означает, что имя сервера было зарегистрировано Если при вызове произошла ошибка, веро- ятнее всего, имя уже используется кем-то другим Код этой ошибки Winsock — WSAEADDR1NUSE (10048 или 0x02740h) Заметьте, что для получения данных процесс должен зарегистрировать имя, вне зависимости от того, обменивае- тесь ли вы дейтаграммами или устанавливаете соединение Разрешение имен AppleTalk Клиентское приложение обычно знает дружественное имя сервера и для вызова функций Winsock должно разрешить его в номер сети, узла и соке- та Эта задача решается путем вызова функции getsockopt с параметром SO_ LOOKUP_NAME Для поиска имени применяется структура WSH_ LOOKUP^ NAME, а также используемая в ней структура WSH_NBP_TUPLE typedef struct WSH_ATALK_ADDRESS Address; f_ ЛЗЯЧТЛ ,ir . „ , < USHORT Enumerator; WSH_NBP_NAME NbpName; } WSH_NBP_TUPLE, *PWSH_NBP_TUPLE; typedef struct _WSH_LOOKUP_NAME // Массив структур WSH_NBP_TUPLE ж*лш .1Ь»ьч,г>{- „;W)XiS/ WSH_NBP_TUPLE LookupTuple; Г Л А В А 6 Семейства адресов и разрешение имен 143 ULONG NoTuples; > WS H_L0OKUP_NAME, *PWSH_LO0KUP_NAME; f При вызове функции getsockopt с параметром SO LOOKUP_NAME мы пе- едаем в нее в качестве буфера структуру WSH_LOOKUP_NAME, а в поле \\ S#_ ЫВР NAME — задаем первый член массива LookupTuple В случае успешного вызова функция getsockopt возвращает массив элементов WSHJVBP_TUPLE, содержащих информацию о физическом адресе для данного имени Поиск имени проиллюстрирован в листинге 6-1 (файл Atalknmc) Кроме того, в примере показано, как перечислить все «обнаруженные» зоны AppleTalk и найти текущую зону Информация о зонах содержится в параметрах SO_ LOOKUP_ZONES и SO_LOOKUP_MYZONE функции getsockopt. Листинг 6-1. Поиск имени и зоны AppleTalk «include «include t «include «include «define DEFAULT.ZONE «define DEFAULT_TYPE "Windows Sockets" «define 0EFAULT_0BJECT "AppleTalk-Server" char szZone[MAX_ENTITY], szType[MAX_ENTITY], szObject[MAX_ENTITY]; BOOL bFmdName = FALSE, bListZones = FALSE, bListMyZone = FALSE; void usage() < printf("usage. atlookup [options]\n"); printf(" Name Lookup \ n " ) , Printf(" -z-ZONE-NAME\n"); ;> printf(" -t TYPE-NAME\n"); p n n t f C к -o-OBJECT-NAME\n"); p n n t f C List All Zones.\n"); Pnntf(" -lz\n"); printf(" List My Zone:\n"); ,о>.<и и P n n t f C -lm\n"); ExitProcessd); } (v void ValidateArgsdnt argc, char "argv) xnt 1 ; T i , jut» • iq aj см.след.стр. и -интерфейс прикладного программирования Winsock Листинг 6-1. (продолжение) strcpy(szZone, DEFAULT_ZONE); strcpy(szType, DEFAULT_TYPE); strcpy(szObject, DEFAULT_OBJECT); for(i = 1; i < argc; i++) { if (strlen(argv[i]) < 2) continue; if ((argv[i][0] == •-') || (argv[i][0] == V ) ) { switch (tolower(argv[i][1])) { case 'z': // Указание имени зоны if (strlen(argv[i]) > 3) strncpy(szZone, &argv[i][3], MAX_ENTITY); bFindName = TRUE; break; case 't': // Указание имени типа if (strlen(argv[i]) > 3) strncpy(szType, &argv[i][3], MAX_ENTITY); bFindName = TRUE; break; case 'о': // Указание имени объекта if (strlen(argv[i]) > 3) strncpyCszObject, &argv[i][3], MAX_ENTITY); bFindName = TRUE; break; case '1'; // Просмотр информации о зонах if (strlen(argv[i]) == 3) // List all zones if (tolower(argv[i][2]) == 'z') bListZones = TRUE; // List my zone %i else if (tolower(argv[i][2]) == 'm') «* bListMyZone = TRUE; break; ; ( ' * default: у.: ( usage(); l • -« . ( int main(int a^b, char **argv) { fc, WSADATA wsd; (vgie»« lerto ,.- s °har J- cLookupBuffer[16000J, •pTupleBuffer = NULL; PWSH_NBP_TBR6 pTuples = NULL; Г Л А В А 6 Семейства адресов и разрешение имен 145 Листинг 6-1. (продолжение) PWSH_LOOKUP_NAME atlookup; PWSH_L00KUP_Z0NES zonelookup; SOCKET s; DWORD dwSize = sizeof(cLookupBuffer); SOCKADDR_AT ataddr; . int i'- // Загрузка библиотеки Winsock // if (WSAStartup(MAKEW0RD(2, 2), &wsd) != 0) < printf("Unable to load Winsock library!\n"); return 1; ValidateArgs(argc, argv); atlookup = (PWSH_LOOKUP_NAME)cLookupBuffer; zonelookup = (PWSH_LOOKUP_ZONES)cLookupBuffer; if (bFindName) // Ввод искомого имени // strcpy(atlookup->LookupTuple.NbpName.ObjectName, szObjeot); atlookup->LookupTuple.NbpName.ObjectNameLen = strlen(szObject); strcpy(atlookup->LookupTuple.NbpName.TypeName, szType); atlookup->LookupTuple.NbpName.TypeNameLen = strlen(szType); strcpy(atlookup->LookupTuple.NbpName.ZoneName, szZone); atlookup->LookupTuple.NbpName.ZoneNameLen = strlen(szZone); } // Создание сокета AppleTalk // s = socket(AF_APPLETALK, SOCK_STREAM, ATPROTO_ADSP); if (s == INVALID_SOCKET) { printf("socket() failed: Xd\n", WSAGetLastErrorO); return 1; } // Для создания в сети AppleTalk конечной точки и выполнения запросов, // необходимо осуществить привязку ZeroMemory(&ataddr, sizeof(ataddr)); ataddr.sat_family = AF.APPLETALK; ataddr.sat_socket = 0; if (bind(s, (SOCKADDR »)&ataddr, sizeof(ataddr)) == INVALID_SOCKET) .imp см. след. стр. 4A(J I ь II Интерфейс прикладного программирования Winsock Листинг 6-1. (продолжение) printf("bind() failed: Xd\n", WSAGetLastErrorO); return 1; if (bFmdName) { printf("Looking up %s: Xs@Xs\n", szObject, szType, szZone); if (getsockopt(s, SOL.APPLETALK, SO_LOOKUP_NAM£, (char Oatlookup, idwSize) == INVALID.SOCKET) { pnntf("getsookopt(SO_LOOKUP_NAME) failed: Xd\n", WSAGetLastErrorO); return 1; > pnntfC'Lookup returned: %d entries\n", atlookup->NoTuples); / / // Символьный буфер содержит массив структур // WSH_NBP_TUPLE, вслед за структурой WSH_L00KUP_NAME // pTupleBuffer = (char *)cLookupBuffer + sizeof(WSH_LOOKUP_NAME); pTuples = (PWSH_NBP_TUPLE) pTupleBuffer; <* for(i = 0; atlookup->NoTuples; ataddr.sat.family = AF_APPLETALK, ataddr.sat.net = pTuples[i].Address.Network; ataddr.sat_node = pTuples[i].Address.Node, ataddr.sat_socket = pTuplesfi].Address. Socket; printf("server address = Xlx.Xlx Xlx.\n", ataddr.sat_net, ataddr.sat_node, ataddr.sat_socket); } else if (bListZones) JAV,- // Для этого параметра необходимо выделить достаточный размер буфера, // иначе в Windows NT 4 SP3 появляется ошибка "синяя смерть" (blue screen) // if (getsockopt(s, SOL_APPLETALK, SO_LOOKUP_ZONES, ом- (char *)atlookup, &dwSize) == INVALID_SOCKET) 8 * ( «7 printf("getsockopt(SO_LOOKUP_NAME) f a i l e d - Xd\n", « e W S A G e t L a s t E r r o r O ) ; > r e t u r n 1; .JAVKA > p n n t f C ' L o o k u p r e t u r n e d : %6 zones\n", zonelookup->NoZonee); Г Л А В А 6 Семейства адресов и разрешение имен Листинг 6-1. {продолжение) II II Буфер содержит список разделенных нулями строк вслед // за структурой WSH_LOOKUP_NAME // pTupleBuffer = (char OcLookupBuffer + sizeof(WSH_LOOKUP_ZONES); for(i = 0; l < zonelookup->NoZones; i++) { printf("X3d: 'Xs'\n", i+1, pTupleBuffer); while (*pTupleBuffer++); else if (bListMyZone) ш II Этот параметр возвращает простую строку if (getsockopt(s, SOL.APPLETALK, S0_LOOKUP_MYZ0NE, (char OcLookupBuffer, &dwSize) == INVALID_SOCKET) { printf("getsockopt(SO_LOOKUP_NAME) failed: Xd\n", WSAGetLastErrorO); return 1; } printf("My Zone: 'J(s'\n", cLookupBuffer); } else " ! usage(); WSACleanup(); return 0; } Для большинства параметров сокетов AppleTalk (например, SO_ LOO- KUP'JMYZONE, SO_LOOKUP_ZONES или SO_LOOKUP_NAME) при вызове функ- ции getsockopt необходимо выделить достаточно большой символьный бу- фер Если в качестве параметра требуется указать структуру, то она должна находиться в начале буфера При успешном вызове функции getsockopt воз- вращаемые данные помещаются в буфер после этой структуры. Рассмотрим раздел с SO_LOOKUP_NAME в листинге 6-1. Для вызова функ- ции getsockopt используется переменная cLookupBuffer, являющаяся простым массивом символов Сначала мы помещаем туда структуру PWSH_LOOKUP_ * с информацией об искомом имени. Затем передаем буфер в функцию 8 sockopt, после чего увеличиваем на 1 указатель на символьный runpTuple- Л ег > чтобы он указывал на символ, находящийся после структуры WSH_ KUP _NAME. Далее присваиваем этому указателю адрес структуры PWSH_ 148 ЧАСТЬ II Интерфейс прикладного программирования Winsock NBPJTUPLE, так как возвращаемые в результате поиска имени данные — массив структур WSH_NBP_TUPLE. Зная начальное положение и тип записей, мы можем просмотреть весь массив. Подробнее о параметрах сокетов — в главе 9. Создание сокета Для создания сокета можно использовать любую подходящую функцию Winsock, начиная с версии 1.1. Существует два способа задать базовые про- токолы AppleTalk: использовать определение соответствующего протокола из файла Atalkwshh, либо вызвать функцию WSAEnumProtocols и поместить результаты в структуру WSAPROTOCOLJNFO. В табл. 6-1 для каждого прото- кола AppleTalk приведены параметры, необходимые для создания сокета функциями socket или WSASocket. Табл. 6-1. Протоколы и параметры AppleTalk, семейство адресов AF APPLETALK Протокол Тип сокета Тип протокола MSAFD AppleTalk [ADSP] SOCK_RDM MSAFD AppleTalk [ADSP] [псевдопоток] SOCKSTREAM MSAFD AppleTalk [PAP] SOCKRDM MSAFD AppleTalk [RTMP] SOCKJXRAM MSAFD AppleTalk [ZIP] SOCKDGRAM ATPROTOADSP ATPROTO_ADSP ATPROTOPAP DDPPROTO_RTMP DDPPROTO ЛР Протокол ATM Winsock 2 в Windows 98 и Windows 2000 поддерживает протокол Async- hronous 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. При использовании этого протокола компьютер может общаться только с ближайшим коммутатором, через несколько коммутаторов данные не передаются. |