Содержание материала

 

Рассмотрим этот файл внимательно. Компилятор транслирует имя RLOG определенное в файле описания интерфейса, в rlog_1, заменяя прописные символы на строчные и добавляя номер версии программы с подчеркиванием. Тип возвращаемого значения изменился с int на int *. Таково правило - RPC позволяет передавать и получать только адреса объявленных при описании интерфейса параметров. Это же правило касается и передаваемой в качестве аргумента строки. Хотя из файла print.h это не следует, на самом деле в качестве аргумента функции rlog_l ( ) также передается адрес строки.

Помимо файла заголовков компилятор rpcgen(l) создает модули заглушки клиента и заглушки сервера. По существу, в тексте этих файлов заключен весь код удаленного вызова.

Заглушка сервера является головной программой, обрабатывающей все сетевое взаимодействие с клиентом (точнее, с его заглушкой). Для выполнения операции заглушка сервера производит локальный вызов функции, текст которой необходимо написать:

log.c

#include <rpc/rpc.>

#include <sys/types.>

#include <sys/stat.>

#include "log.h"

int *rlog_1 (char **arg)

{

/*Возвращаемое значение должно определяться как static*/

static int result;

int fd; /*Файловый дескриптор журнала*/

int len;

result = 1;

/*0ткроем файл журнала (создадим, если он не существует), в случае неудачи вернем код ошибки result == 1.*/

if ((fd=open( "./server .log",

O_CREAT | O_RDWR | O_APPEND)) < 0) return (&result);

len = strlen(*arg);

if (write(fd, *arg, strlen(*arg)) != len)

result = 1;

else

result = 0;

close (fd);

return(&result); /*Возвращаем результат - адрес result*/

}

Заглушка клиента принимает аргумент, передаваемый удаленной процедуре, делает необходимые преобразования, формирует запрос на сервер portmap(1M), обменивается данными с сервером удаленной процедуры и, наконец, передает возвращаемое значение клиенту. Для клиента вызов удаленной процедуры сводится к вызову заглушки и ничем не отличается от обычного локального вызова.

client.c

#include <rpc/rpc.>

#include "log.h"

main(int argc, char *argv[])

{

CLIENT *cl;

char *server, *mystring, *clnttime;

time_t bintime;

int *result;

if (argc != 2) {

fprintf(stderr, "Формат вызова: %s Адрес_хоста\n",

argv [0]);

exit (1) ;

}

server = argv [1];

/*Получим дескриптор клиента. В случае неудачи - сообщим о

невозможности установления связи с сервером*/

if ( (с1 = clnt_create (server,

LOG_PROG, LOG_VER, "udp")) == NULL) {

clnt_pcreateerror (server);

exit (2);

}

/*Выделим буфер для строки*/

mystring = (char * )malloc (100);

/*Определим время события*/

bintime = time ((time_t * ) NULL);

clnttime = ctime(&bintime);

sprintf (mystring, "%s - Клиент запущен", clnttime);

/*Передадим сообщение для журнала - время начала работы клиента. В случае неудачи - сообщим об ошибке*/

if ( (result = rlog_l(&mystring, cl)) == NULL) {

fprintf(stderr, "error2\n");

clnt_perror(cl, server);

exit(3);

}

/*B случае неудачи на удаленном компьютере сообщим об ошибке*/

if (*result !=0 )

fprintf(stderr, "Ошибка записи в журнал\n");

/*0свободим дескриптор*/

cint destroy(cl);

exit (0);

}

Заглушка клиента log_clnt.c компилируется с модулем client.c для получения исполняемой программы клиента.

cc -о rlog client.c log_clnt.c -Insl

Заглушка сервера log_svc.c и процедура log.c компилируются для получения исполняемой программы сервера.

cc -о logger log_svc.c log.c -Insl

Теперь на некотором хосте server.nowhere.ru необходимо запустить серверный процесс:

$ logger

После чего при запуске клиента rlog на другой машине сервер добавит соответствующую запись в файл журнала.

Схема работы RPC в этом случае приведена на рис. 1. Модули взаимодействуют следующим образом:

1. Когда запускается серверный процесс, он создает сокет UDP и связывает любой локальный порт с этим сокетом. Далее сервер вызывает библиотечную функцию svc_register(3N) для регистрации номеров программы и ее версии. Для этого функция обращается к процессу portmap(IM) и передает требуемые значения. Сервер portmap(IM) обычно запускается при инициализации системы и связывается с некоторым общеизвестным портом. Теперь portmap(3N) знает номер порта для нашей программы и версии. Сервер же ожидает получения запроса. Заметим, что все описанные действия производятся заглушкой сервера, созданной компилятором rpcgen(IM).

2. Когда запускается программа rlog, первое, что она делает, - вызывает библиотечную функцию clnt_create(3N), указывая ей адрес удаленной системы, номера программы и версии, а также транспортный протокол. Функция направляет запрос к серверу portmap(IM) удаленной системы server.nowhere.m и получает номер удаленного порта для сервера журнала.

3. Клиент вызывает процедуру rlog_1 ( ) , определенную в заглушке клиента, и передает управление заглушке. Та, в свою очередь, формирует запрос (преобразуя аргументы в формат XDR) в виде пакета UDP и направляет его на удаленный порт, полученный от сервера portmap(IM). Затем она некоторое время ожидает отклика и в случае неполучения повторно отправляет запрос. При благоприятных обстоятельствах запрос принимается сервером logger (модулем заглушки сервера). Заглушка определяет, какая именно функция была вызвана (по номеру процедуры), и вызывает функцию rlog_1 ( ) модуля log.c. После возврата управления обратно в заглушку последняя преобразует возвращенное функцией rlog_1 ( ) значение в формат XDR, и формирует отклик также в виде пакета UDP. После получения отклика заглушка клиента извлекает возвращенное значение, преобразует его и возвращает в головную программу клиента.

Добавить комментарий

Не использовать не нормативную лексику.

Просьба писать ваши замечания, наблюдения и все остальное,
что поможет улучшить предоставляемую информацию на этом сайте.

ВСЕ КОММЕНТАРИИ МОДЕРИРУЮТСЯ ВРУЧНУЮ, ТАК ЧТО СПАМИТЬ БЕСПОЛЕЗНО!


Защитный код
Обновить