Электронная библиотека книг Александра Фролова и Григория Фролова.
 
Библиотека
Братьев
Фроловых
Электронная библиотека книг Александра Фролова и Григория Фролова.
Библиотека системного программиста
Программирование на JAVA
ПК. Шаг за шагом
Другие книги
Восстановление данных
Антивирусная защита
Статьи для
программистов
Пользователю компьютера

Локальные сети персональных компьютеров. Использование протоколов IPX, SPX, NETBIOS

© Александр Фролов, Григорий Фролов
Том 4, М.: Диалог-МИФИ, 1993, 160 стр.

[Назад] [Содеожание] [Дальше]

2.5. Пример c использованием ESR

В предыдущем примере при ожидании пакета мы опрашивали в цикле поле InUse блока ECB. Однако более эффективным является использование программы ESR. Эта программа получает управление тогда, когда пакет принят и поле InUse установлено в ноль.

Когда ESR получает управление, регистры процессора содержат следующие значения:

AL идентификатор вызывающего процесса:
FFh - программа ESR вызвана драйвером IPX;
00h - программа ESR вызвана планировщиком асинхронных событий AES (будет описан позже);
ES:SI адрес блока ECB, связанного с данной ESR.

Содержимое всех регистров, кроме SS и SP, а также флаги процессора записаны в стек программы.

Если ESR будет обращаться к глобальным переменным программы, необходимо правильно загрузить регистр DS. Непосредственно перед вызовом ESR прерывания запрещаются. Функция ESR не возвращает никакого значения и должна завершать свою работу командой дальнего возврата RETF. Перед возвратом управления прерывания должны быть запрещены.

Обычно ESR используется для установки ECB, связанных с принятыми пакетами, в очередь на обслуживание. Как и всякая программа обработки прерывания, выполняющаяся в состоянии с запрещенными прерываниями, ESR должна выполнять минимально необходимые действия и быстро возвращать управление прерванной программе.

Наша программа-ESR (листинг 8) выполняет простую задачу - записывает адрес связанного с ней блока ECB в глобальную переменную completed_ecb_ptr, которая сбрасывается в главной программе перед ожиданием приема пакета. Программа-клиент (листинг 7), ожидая прихода пакета, выполняет какие-либо действия (в нашем случае она просто вводит символы с клавиатуры и выводит их на экран) и периодически опрашивает глобальную переменную. Как только пакет будет принят, в эту переменную будет записан отличный от нуля адрес блока ECB.

// ===================================================
// Листинг 7. Клиент IPX
// Файл ipxclien.c
//
// (C) A. Frolov, 1993
// ===================================================

#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include <mem.h>
#include <string.h>
#include <dos.h>
#include "ipx.h"

// Максимальный размер буфера данных

#define BUFFER_SIZE 512

extern struct ECB far * completed_ecb_ptr;
extern void far         ipxspx_esr(void);

void main(void) {

// Будем работать с сокетом 0x4567

        static unsigned Socket = 0x4567;

// ECB для приема и передачи пакетов

        struct ECB RxECB, TxECB;

// Заголовки принимаемых и передаваемых пакетов

        struct IPX_HEADER RxHeader, TxHeader;

// Буферы для принимаемых и передаваемых данных

        unsigned char RxBuffer[BUFFER_SIZE];
        unsigned char TxBuffer[BUFFER_SIZE];

        printf("\n*Клиент IPX*, (C) Фролов А., 1993\n\n");

// Проверяем наличие драйвера IPX и определяем
// адрес точки входа его API

        if(ipx_init() != 0xff) {
                printf("IPX не загружен!\n"); exit(-1);
        }

// Открываем сокет, на котором будем принимать и передавать пакеты

        if(IPXOpenSocket(SHORT_LIVED, &Socket)) {
                printf("Ошибка при открытии сокета\n");
                exit(-1);
        };

// Подготавливаем ECB для передачи пакета

        memset(&TxECB, 0, sizeof(TxECB));

        TxECB.Socket            = IntSwap(Socket);
        TxECB.FragmentCnt       = 2;
        TxECB.Packet[0].Address = &TxHeader;
        TxECB.Packet[0].Size    = sizeof(TxHeader);
        TxECB.Packet[1].Address = TxBuffer;
        TxECB.Packet[1].Size    = BUFFER_SIZE;

// Пакет предназначен всем станциям данной сети

        memset(TxECB.ImmAddress, 0xff, 6);

// Подготавливаем заголовок пакета

        TxHeader.PacketType = 4;
        memset(TxHeader.DestNetwork, 0, 4);
        memset(TxHeader.DestNode, 0xff, 6);
        TxHeader.DestSocket = IntSwap(Socket);

// Записываем передаваемые данные

        strcpy(TxBuffer, "ESR/CLIENT *DEMO*");

// Передаем пакет всем станциям в данной сети

        IPXSendPacket(&TxECB);

        completed_ecb_ptr = (unsigned long)0;

// Подготавливаем ECB для приема пакета от сервера

        memset(&RxECB, 0, sizeof(RxECB));
        RxECB.Socket            = IntSwap(Socket);
        RxECB.FragmentCnt       = 2;
        RxECB.Packet[0].Address = &RxHeader;
        RxECB.Packet[0].Size    = sizeof(RxHeader);
        RxECB.Packet[1].Address = RxBuffer;
        RxECB.Packet[1].Size    = BUFFER_SIZE;
        RxECB.ESRAddress        = ipxspx_esr;

        IPXListenForPacket(&RxECB);

        printf("Ожидание ответа от сервера\n");
        printf("Нажимайте любые клавиши\n");
        printf("Для отмены нажмите клавишу <ESC>\n");

// Ожидаем прихода ответа от сервера

        while(completed_ecb_ptr == NULL) {
                if( getche() == 27) {
                        IPXCloseSocket(&Socket);
                        exit(0);
                }
        }
        if(RxECB.CCode == 0) {
                printf("\nПринят ответ от сервера '%s'\n", RxBuffer);
        }

// Закрываем сокет

        IPXCloseSocket(&Socket);
        exit(0);
}



В листинге 8 приведен текст программы ESR, составленный на языке ассемблера. Программа загружает регистр DS адресом сегмента данных программы, затем записывает в глобальную переменную completed_ecb_ptr содержимое регистров ES:SI.

; ===================================================
; Листинг 8. Программа ESR
; Файл esr.asm
;
; (C) A. Frolov, 1992
; ===================================================

.286
.MODEL SMALL

.DATA

        _completed_ecb_ptr dd 0

.CODE

        PUBLIC   _ipxspx_esr
        PUBLIC  _completed_ecb_ptr

_ipxspx_esr PROC FAR

                mov     ax, DGROUP
                mov     ds, ax

                mov     word ptr _completed_ecb_ptr+2, es
                mov     word ptr _completed_ecb_ptr, si

                retf
_ipxspx_esr ENDP

end



[Назад] [Содеожание] [Дальше]


Создание интернет-магазинов: http://www.shop2you.ru/ © Александр Фролов, Григорий Фролов, 1991-2016