Локальные сети персональных компьютеров. Использование протоколов IPX, SPX, NETBIOS© Александр Фролов, Григорий ФроловТом 4, М.: Диалог-МИФИ, 1993, 160 стр. 4.2. Работа с протоколом NETBIOSПротокол NETBIOS предоставляет программам интерфейс для передачи данных на уровне датаграмм и на уровне каналов связи. Для вызова NETBIOS программа должна создать в памяти управляющий блок, который называется NCB (Network Control Block - сетевой управляющий блок). Адрес заполненного блока NCB передается прерыванию INT 5Ch, в рамках которого и реализован интерфейс протокола NETBIOS. Есть также альтернативный интерфейс, реализованный в рамках прерывания INT 2Ah, который поддерживается эмулятором NETBIOS, разработанным фирмой Novell, а также операционной системой Windows for Workgroups версии 3.1. 4.2.1. Проверка присутствия NETBIOSПервое, что должна сделать программа, желающая воспользоваться протоколом NETBIOS, - проверить наличие в системе интерфейса NETBIOS. Ниже приведена программа, которая определяет, установлен ли драйвер NETBIOS. С помощью функции getvect() программа получает указатель на обработчик прерывания INT 5Ch. Это прерывание используется для вызова NETBIOS. Если сегментная компонента адреса равна нулю или F000h, обработчик прерывания не установлен или установлена заглушка, расположенная в BIOS. В этом случае программа считает, что NETBIOS отсутствует. // =================================================== // Листинг 16. Проверка присутствия NETBIOS // // Файл nbver.cpp // // (C) A. Frolov, 1993 // =================================================== #include <stdio.h> #include <stdlib.h> #include <dos.h> #include <conio.h> #include <mem.h> #include <string.h> void main(void) { void interrupt ( *int5C)(...); printf("Check if NETBIOS is installed\n"); int5C = getvect(0x5c); if(FP_SEG(int5C) == 0x0000 || FP_SEG(int5C) == 0xF000) { printf("NETBIOS NOT installed.\n"); } else printf("NETBIOS is installed!\n"); } Другой способ проверки наличия интерфейса NETBIOS
заключается в вызове прерывания INT 2Ah.
Загрузите в регистр AH нулевое значение и
вызовите прерывание INT 2Ah. Если после возврата
из прерывания в регистре AH Данный способ проверки будет работать на виртуальной машине DOS, запущенной в среде Windows for Workgroups версии 3.1 (если Windows работает в расширенном режиме). Приведенная ниже программа определяет присутствие NETBIOS с помощью вызова прерывания INT 2Ah (листинг 17): // =================================================== // Листинг 17. Проверка присутствия NETBIOS // с использованием интерфейса INT 2Ah // // Файл 2atest.cpp // // (C) A. Frolov, 1993 // =================================================== #include <stdio.h> #include <stdlib.h> #include <dos.h> #include <conio.h> #include <mem.h> #include <string.h> void main(void) { union REGS regs; printf("Check if NETBIOS is installed\n"); regs.h.ah = 0; int86(0x2a, ®s, ®s); if(regs.h.ah == 0) { printf("NETBIOS NOT installed.\n"); } else printf("NETBIOS is installed!\n"); } Прерывание INT 2Ah используется в сетях фирм Microsoft и Lantastic. Эмулятор протокола NETBIOS, поставляющийся фирмой Novell вместе с операционной системой Novell NetWare, поддерживает как интерфейс прерывания INT 5Ch, так и интерфейс INT 2Ah. 4.2.2. Вызов команд протокола NETBIOSИнтерфейс протокола NETBIOS реализован в рамках прерывания INT 5Ch или INT 2Ah и очень прост. Для вызова команд протокола NETBIOS вам достаточно подготовить блок NCB, загрузить его дальний адрес в регистры ES:BX и вызвать прерывание INT 5Ch. Приведем формат вызова функции прерывания INT 2Ah, предназначенной для выполнения команд NETBIOS:
Вы можете использовать описанный выше вызов прерывания INT 2A для вызова NETBIOS из программы, работающей на виртуальной машине Windows for Workgroups версии 3.1. Для вызова команд протокола NETBIOS из пограммы, составленной на языке Си, вы можете воспользоваться обычными средствами вызова программных прерываний, такими, как функция int86x(). 4.2.3. Формат блока NCBПриведем формат блока NCB: struct _NCB { unsigned char Cmd; unsigned char CCode; unsigned char LocalSessionNumber; unsigned char NetworkNameNumber; void far *Buffer; unsigned Size; char CallName[16]; char OurName[16]; unsigned char ReceiveTimeout; unsigned char SendTimeout; void interrupt (*PostRoutine)(void); unsigned char AdapterNumber; unsigned char FinalCCode; unsigned char Reserved[14]; }; Поле Cmd содержит код команды, которую
необходимо выполнить. Существуют команды для
работы с именами станций, для передачи и приема
дата- Поле CCode содержит код ошибки, возвращаемый NETBIOS до выполнения команды. Если, например, программа затребовала выполнение неправильной команды или задала для команды неправильные параметры, NETBIOS не будет выполнять такую команду и установит в поле CCode соответствующий код ошибки. Если же в этом поле после вызова NETBIOS находится нулевое значение, это еще не означает, что команда выполнилась правильно, однако она начала выполняться. Поле LocalSessionNumber содержит номер канала, установленного с другой программой. Это поле необходимо заполнять при выдаче команд передачи данных через каналы. Поле NetworkNameNumber содержит номер имени, который присваивается при добавлении обычного или группового имени. Это поле должно быть заполнено при приеме датаграмм. Поле Buffer представляет собой дальний указатель в формате [сегмент:смещение] на буфер, который должен содержать данные перед выполнением передачи или на буфер, который будет использован для приема данных. Размер буфера, используемого для приема или передачи данных, определяется содержимым поля Size. Поле CallName заполняется именем станции, с которой ваша станция желает установить канал для передачи данных. Поле OurName должно содержать имя вашей программы, под которым она будет принимать данные. В качестве этого имени может выступать обычное, групповое или постоянное имя. Поля ReceiveTimeout и SendTimeout содержат интервал времени (измеряемый в 1/2 с), в течение которого ожидается завершение соответственно команд приема и передачи. Поле PostRoutine - указатель на программу, которая получает управление после завершения команды. Эта программа (POST-программа) аналогична программе ESR протоколов IPX/SPX и вызывается только в том случае, если в поле PostRoutine был указан адрес программы. Если же это поле заполнить нулями, никакая программа вызываться не будет. Поле AdapterNumber используется, если в станции установлено несколько сетевых адаптеров (в сетях Ethernet этого обычно не бывает). В этом поле указывается номер адаптера, для которого предназначена команда. Первый адаптер имеет номер 0, второй - 1. Поле FinalCCode содержит во время выполнения команды значение 0xFF. После завершения выполнения команды в это поле записывается код ошибки, который относится к выполнению команды в целом (в отличие от кода в поле CCode). Если ваша программа не задала адрес для программы в поле PostRoutine, она должна опрашивать в цикле содержимое этого поля, ожидая, пока в нем не появится значение, отличное от 0xFF. Поле Reserved зарезервировано для использования протоколом NETBIOS, ваша программа не должна изменять его содержимое. 4.2.4. POST-программаPOST-программа является программой обработки
прерывания. Она получает управление в состоянии
с запрещенными прерываниями. Регистры ES:BX
содержат адрес блока NCB, который использовался
при выполнении команды. Учтите, что, как и из любой другой программы обработки прерывания, из POST-программы не следует вызывать функции MS-DOS. Требования к POST-программе во многом такие же, как и к ESR-программе, используемой протоколами IPX и SPX. Она должна позаботиться о сохранении изменяемых регистров, установить регистр DS на сегмент данных программы (для обеспечения доступа к переменным). POST-программа должна работать как можно быстрее. Лучше всего если она будет использоваться только для установки флага, сигнализирующего основной программе о завершении выполнения команды. Перед завершением своей работы POST-программа должна восстановить содержимое всех регистров и выполнить команду возврата из прерывания IRET. Если вы составляете POST-программу на языке программирования Си, вы можете воспользоваться ключевым словом interrupt: void interrupt NETBIOS_Post_Routine(void); Лучше всего составить POST-программу на языке ассемблера, например, так: .286 .MODEL SMALL .DATA _completed_ncb_ptr dd 0 .CODE PUBLIC _netbios_post PUBLIC _completed_ncb_ptr _netbios_post PROC FAR push ax push ds push es push si mov ax, DGROUP mov ds, ax mov word ptr _completed_ncb_ptr+2, es mov word ptr _completed_ncb_ptr, si pop si pop es pop ds pop ax iret _netbios_post ENDP end |