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



                  

  

Если оболочка не загружена, завершаем



Листинг 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. // ===================================================

Содержание  Назад  Вперед