Локальные сети персональных компьютеров. Работа с сервером Novell NetWare


Листинг 4



Листинг 4

Функции для программы SLIST.CPP // Файл slist!\sap.cpp // // (C) A. Frolov, 1993 // =================================================== #include <stdlib.h> #include <stdio.h> #include <mem.h> #include <string.h> #include <dos.h> #include "sap.hpp" // ==================================================== // Конструктор класса SLIST // ==================================================== SLIST::SLIST(int ServiceType) { // Проверяем наличие сетевой оболочки и определяем ее версию MajorVersion = 0; asm push si GetNetWareShellVersion(&MajorVersion, &MinorVersion, &Revision); asm pop si // Если оболочка не загружена, завершаем работу // программы с сообщением об ошибке if(MajorVersion == 0) { printf("\nОболочка NetWare не загружена\n"); errno = 0xff; return; } // Проверяем тип SAP-запроса if (ServiceType != 1 && ServiceType != 3) { errno = NOT_SUPPORTED; return; } // Запоминаем тип запроса QueryType = ServiceType; // Инициализируем драйвер протокола IPX IPXInitialize(); // Открываем короткоживущий динамический сокет SrcSocket = 0x00; errno = IPXOpenSocket(&SrcSocket, SHORT_LIVED); // Заполняем таблицу имен серверов нулями memset(ServerName,0,sizeof(ServerName)); // Подготавливаем блоки ECB для приема // пакетов от SAP-протокола for(int i=0;i<MAX_SERVERS;i++) { // Заполняем блок ECB ReceiveSAPPacket(&Query[i]); // Ставим в очередь на прием пакета IPXListenForPacket(&Query[i].theECB); } // Если не было ошибок, посылаем запрос if (!errno) { SendSAPPacket(); // Ждем примерно одну секунду sleep(1); // Переписываем имена серверов и другую информацию GetServersName(); GetServersInfo(); } } // ==================================================== // Деструктор класса SLIST // ==================================================== SLIST::~SLIST() { // Отменяем ожидающие блоки ECB for(int i=0;i<MAX_SERVERS;i++) { IPXCancelEvent(&Query[i].theECB); } // Закрываем сокет IPXCloseSocket(SrcSocket); } // ==================================================== // Посылка SAP-запроса // ==================================================== void SLIST::SendSAPPacket(void) { // Сбрасываем поле inUseFlag и ESRAddress, устанавливаем тип пакета 0 SendPacket.theECB.inUseFlag = 0; SendPacket.theECB.ESRAddress = 0; SendPacket.SAPq.packetType = 0; // SAP-пакет состоит из одного фрагмента. Записываем в ECB // количество фрагментов, адрес и размер буфера SendPacket.theECB.fragmentCount = 1; SendPacket.theECB.fragmentDescriptor[0].address = &SendPacket.SAPq; SendPacket.theECB.fragmentDescriptor[0].size = sizeof(SAPQueryPacket); // Записываем в ECB номер своего сокета SendPacket.theECB.socketNumber = SrcSocket; // Устанавливаем адрес назначения - все станции в текущей сети, // сокет SAP_SOCKET. Устанавливаем поле непосредственного адреса memset(SendPacket.SAPq.destination.network, '\x00', 4); memset(SendPacket.SAPq.destination.node, '\xFF', 6); SendPacket.SAPq.destination.socket = IntSwap(SAP_SOCKET); memset(SendPacket.theECB.immediateAddress, '\xFF', 6); // Устанавливаем свой адрес в заголовке запроса IPXGetInternetworkAddress(SendPacket.SAPq.source.network); SendPacket.SAPq.source.socket = IntSwap(SrcSocket); // Заполняем передаваемый пакет. Устанавливаем тип запроса // и тип сервера SendPacket.SAPq.queryType = IntSwap(QueryType); SendPacket.SAPq.serverType = IntSwap(0x0004); // Посылаем SAP-пакет IPXSendPacket(&SendPacket.theECB); // Ожидаем завершения процесса передачи пакета while (SendPacket.theECB.inUseFlag) IPXRelinquishControl(); // Сохраняем код возврата errno = SendPacket.theECB.completionCode; } // ==================================================== // Прием SAP-пакетов // ==================================================== void SLIST::ReceiveSAPPacket(RECEIVE_PACKET *Query) { // Сбрасываем поле inUseFlag и ESRAddress Query->theECB.inUseFlag = 0; Query->theECB.ESRAddress = 0; // Записываем в ECB количество фрагментов, адрес и размер буфера Query->theECB.fragmentCount = 1; Query->theECB.fragmentDescriptor[0].address = &Query->SB; Query->theECB.fragmentDescriptor[0].size = sizeof(Query->SB); // Устанавливаем в ECB свой номер сокета Query->theECB.socketNumber = SrcSocket; } // ==================================================== // Процедура переписывает имена серверов из тех // блоков ECB, для которых пришли пакеты // ==================================================== void SLIST::GetServersName(void) { for(int i=0,j=0; i<MAX_SERVERS; i++) { if(!Query[i].theECB.inUseFlag) { strcpy(ServerName[j],Query[i].SB.ServerName); j++; } } } // ==================================================== // Процедура получает информацию о серверах // ==================================================== void SLIST::GetServersInfo(void) { // Получаем номера каналов первичного сервера // и сервера по умолчанию PrimaryConnID = GetPrimaryConnectionID(); DefaultConnID = GetDefaultConnectionID(); // Цикл по всем обнаруженным в сети активным серверам for(int i=0; i<MAX_SERVERS; i++) { if(ServerName[i][0]) { // Получаем номер канала сервера errno = GetConnectionID(ServerName[i], &ConnID[i]); // Если канала нет, создаем его, подключаясь к серверу if(errno) { AttachToFileServer(ServerName[i], &ConnID[i]); } // Делаем текущий сервер предпочтительным, так как // именно к нему должны поступать запросы errno = SetPreferredConnectionID(ConnID[i]); // Получаем информацию о текущем сервере if(!errno) errno = GetServerInformation(sizeof(ServerInfo[i]), &ServerInfo[i]); // Получаем серийный номер и номер приложения SerialNumber[i]=ApplicationNumber[i]=0L; errno = GetNetworkSerialNumber(&SerialNumber[i], &ApplicationNumber[i]); errno = 0; } } } // ============================================================ // Процедура распечатывает имена и другую информацию о серверах // ============================================================ void SLIST::PrintServersName(void) { // Цикл по всем обнаруженным в сети активным серверам for(int i=0; i<MAX_SERVERS; i++) { if(ServerName[i][0]) { // Выводим имя сервера printf("%s",ServerInfo[i].serverName); // Если номер канала текущего сервера совпадает с // номером канала первичного сервера, выводим строку "\t[Primary]" if(ConnID[i] == PrimaryConnID) printf("\t[Primary]"); else printf("\t[ ]"); // Если номер канала текущего сервера совпадает с // номером канала сервера по умолчанию, выводим строку " [Default]" if(ConnID[i] == DefaultConnID) printf(" [Default]"); else printf(" [ ]"); // Выводим версию сетевой операционной системы, // работающей на текущем сервере printf(" v.%d.%d, ", ServerInfo[i].netwareVersion, ServerInfo[i].netwareSubVersion); // Для подключенных серверов выводим серийный // номер и номер приложения if(SerialNumber[i] != 0L) printf("s/n %08.8lX/%04.4X", SerialNumber[i], ApplicationNumber[i]); else printf("- Not Logged In -"); // Выводим номер канала, используемого для связи с текущим сервером printf("\tConnID: %d,",ConnID[i]); // Выводим максимальное число каналов, поддерживаемых // сервером, и количество используемых каналов printf(" (%d-%d)\n", ServerInfo[i].maxConnectionsSupported, ServerInfo[i].connectionsInUse); } } }

Файл sap.hpp содержит все определения констант и описания структур, необходимые для программы SLIST. В частности, в этом файле описан класс SLIST. // ===================================================









Начало  Назад  Вперед