Программирование >>  Структура ядра и системные вызовы 

1 ... 73 74 75 [ 76 ] 77 78 79 ... 98


cerr client authentication setup failsXn ; perror( authdes seccreate ); clnt perror(clntp,server); clntp->cl auth = authnone create();

#endif

} break; default:

cerr authentication method (int)choice

not yet supportedXn ; clntp->cl auth = authnone create0;

/* Вызов RPC-функции */

int call( unsigned procnum, xdrproc t xdr ifunc, caddr t argp, xdrproc t xdr ofunc, caddr t rsltp, unsigned timeout = 20 )

if (!clntp) return -1; struct timeval timv; timv.tv sec = timeout; timv.tv usec =0;

if (clnt call(clntp, procnum, xdr ifunc, argp,

, xdr ofunc, rsltp, timv)!=RPC SUCCESS)

clnt perror(clntp, server); return -2;

return RPC SUCCESS;

/* Поддержка широковещательного режима */

static int broadcast( unsigned prognum, unsigned versnum,

unsigned procnum, resultproc t callbaclt, xdrproc t xdr ifunc, caddr t argp, xdrproc t xdr ofunc, caddr t rsltp, char* nettype = datagram v )

#ifdef SYSV4

return rpc broadcast(prognum, versnum, procnum, xdr ifunc, argp, xdr ofunc, rsltp, callbacjc, nettype);

#else

return clnt broadcast(prognum, versnum, procnum, xdr ifunc, argp, xdr ofunc, rsltp, callbac)<);

#endif

,/* Установить тайм-аут для клиента */ int set timeout( long usee )

if (!clntp) return -1;

struct timeval timv; timv.tv sec = 0; timv.tv usec = usee;

return clnt control( clntp, CLSET TIMEOUT, (char*)Stimv);

/* Получить тайм-аут клиента */

long get timeoutО

if (!clntp) return -1; struct timeval timv;

if (clnt control( clntp, CLGET TIMEOUT, (char*)Stimv)==-1)

perror( clnt control ); return -1;

return timv.tv usee;

tendif /* RPC H */

Последовательность вызова функций-членов этих классов для типичных клиента и сервера показана на рис. 12.2.

Клиент

RPC cls::RPC cIs

RPC cls::set auth RPC cls::call

Сервер

RPC svc::RPC svc

RPC svc::run func

RPC svc::getargs

RPC svc::reply

Рис. 12.2. Функции клиентского и серверного классов RPC и последовательность их вызова

Функция-конструктор RPCsvcr.RPCsvc создает обработчик вызовов RPC-сервера для заданного номера RPC-программы и заданного номера RPC-версии. Кроме того, эта функция регистрирует пользовательскую функцию-Диспетчер, которая активизируется, когда клиент вызывает RPC-функцию, управляемую сервером. Последний аргумент функции RPCsvcr.RPCsvc - значение nettype. Оно задает транспортный протокол для связи между сервером и его клиентами. Функция RPC svc.:RPC svc вызывает API svc create, который создает интерфейс к серверному процессу. Пользователи могут



модифицировать функцию RPC svc::RPC svc, чтобы вместо svcjcreate она вызывала svc tp create или svc tli create.

Функция RPC svc::run /ипс вызывается для регастрации на сервере RPC-функции и присвоенного ей номера процедуры, а затем блокирует сервер и переводит его в режим ожидания клиентских RPC-вызовов (через API svc run). Если пользователь хочет зарегистрировать на сервере более одной RPC-функции, серверную программу необходимо соответствующим образом изменить:

RPC svc svcp = new RPC svc(...);

if (Isvcp II svcp->good()) return 1;

svcp->add func (<procnuniI>, prog2) ;

svcp->add func (<procnuniW-I>, progN-1) ; svcp->run func (<procnuniW>, progN) ;

Когда поступает клиентский RPC-запрос, то вызывается зарегистрированная с помощью функции RPC svc::RPC svc функция-диспетчер, которая обслуживает клиентский запрос.

Функция-диспетчер проверяет, равен ли затребованный клиентом RPC-у. номер нулю. Если равен, то клиент просто запрашивает сервер, а сервер

просто посылает клиенту ответ с NULL-значением.

Если клиент указывает какие-то аутентификахдаонные данные, диспетчер проверяет их и при отрицательном результате выставляет флаг ошибки аутентификации. В данной функции аутентификация клиента выполняется по усмотрению сторон. Если речь идет о защите RPC-транзакций, то аутентификация обязательна. Сервер должен всегда требовать, rгoбы клиенты посылали аутентификационные данные в каждом RPC-вызове. Метод RPC-аутентификации рассматривается в одном из следующих разделов.

При положительном результате аутентификации диспетчер вызывает RPC-функцию, затребованную клиет-ом.

Каждая RPC-функция, вызываемая функцией RPCjsvc::dispatch, должна иметь следующий прототип:

int <имя функции> (SVCXPRT*);

где аргументом является указатель на обработчик для механизма транспортировки, используемого для связи с конечной точкой транспортировки клиента. В случае успешного выполнения функция возвращает нуль (RPC SUCCESS), а в случае неудачи - ненулевое значение. Помимо этого данная RPC-функция должна обрабатывать глобальный указатель RPCjsvc * (имя его переменной определяется приложением), в котором находится адрес указателя на RPC-сервер. Функция сначала должна вызвать RPC svc::getargs, чтобы извлечь аргументы из клиентского запроса, а затем RPCjsvcr.reply, чтобы передать клиенту возвращенное ею значение.

В клиентской профамме обработчик клиента для заданных номеров профаммы и версии создается с помощью функции-конструктора RPC cls::RPC cls. Эта функция получает указатель на клиента путем внутреннего вызова API clnt create. Как и функция-конструктор RPCsvc, функция RPCcbr.RPCcls может бьггь модифицирована пользователями так, чтобы вызывать не clntjcreate, а clnt tp create или clnt tli create.

Аутентификационные данные клиента можно установить, вызвав функцию RPC cls::set Класс RPC cls поддерживает режимы AUTH NONE, AUTH SYS и AUTH DES, но пользователи могуг модифицировать функцию RPC cls::set auth, чтобы реализовать собственные методы аутентификации. Методы аутентификации AUTH NONE, AUTH SYS и AUTH DES рассмотрены в одном из следующих разделов. В ONC вместо AUTH SYS используется AUTH UNIX.

Клиент вызывает RPC-функцию с помощью функции RPC cls::call. Аргументами функции RPC cls::call являются номер RPC-процедуры, XDR-функция, преобразующая входные аргументы в формат XDR, адрес переменной, в которой содержатся входные аргументы, XDR-функция, преобразующая значение, возвращенное данной RPC-функцией (из формата XDR в формат локальной машины), и адрес переменной, содержащей значение, возвращенное RPC-функцией. При успешном выполнении функция RPC cls::call возвращает RPCSUCCESS, а в случае неудачи - ненулевое значение.

Статическая функция RPC cls:broadcast обеспечивает передачу широковещательных RPC-запросов из клиентского процесса по сети всем серверным процессам. Подробно эта функция рассмотрена в разделе 12.8.

Приложения, в которых используются классы RPC, в различных коммерческих разновидностях UNIX должны компилироваться со следующими опциями:

Разновидность UNIX

Опции компиляции СС

Solaris 2.x Sun OS 4.1.x HP-UX 9.0.x IBM AIX 3.x и 4.x SCO 3.x

-DSYSV4 -Isocket -Insl *-Insl Нет

-Irpcsvc

-Isocket

Эти опции компиляции показывают, какие системные библиотеки RPC нужно связывать с пользовательскими приложениями в разных UNIX-системах. Опция -DSYSV4 в системе Solaris 2.x необходима для того, чтобы вместо API ONC использовались API RPC UNIX System V.4.

Чтобы проиллюстрировать использование классов RPC, перепишем профамму удаленной печати сообщений, приведенную в разделе 12.3. Обратите внимание на то, что новые клиентская и серверная профаммы проще предыдущих версий, в которых используется компилятор rpcgen.



Клиентская программа msg cls2.C ъышящгг следующим образом:

/* Клиентская программа: использование низкоуровневых API RPC tinclude msg2.h ♦include RPC.h

int main(int argc, char* argv[]) {

if (argc<3) (

cerr usage: argv[0] << host msg <nettype>\n ; . return 1;

II? (

/f Создать обработчик клиента для RPC-сервера */ ,1.}}

RpC cls с1( argv[l], MSGPROG, MSGVER, argc>=4 ? argv[3]: netpath ); if (Icl.goodO) return 1;

/* Вызвать RPC-функцию printmsg. Возвращаемое значение

устанавливается в res */ int res;

if (cl.calK PRIMTMSG, (xdrproc t)xdr string, (caddr t)sargv[2], (xdrproG t)xdr int, (caddr t)Sres) != RPC SUCCESS)

return 3;

/* Проверить возвращаемое значение RPC-функции */ if (res!=0)

cerr clnt: call printmsg fails\n ; else cout clnt: call printmsg succeeds\n ;

return 0;

Эта клиентская программа вызывается с двумя или тремя аргументами. Первый аргумент - хост-имя машины, на которой работает RPC-сервер. Это может быть имя локальной машины, если клиент и сервер работают на одном компьютере. Второй аргумент - символьная строка сообщения, передаваемого на RPC-сервер для вывода на печать. Третий аргумент (необязательный) - это транспортный протокол, который должен использоваться клиентом для связи с сервером. Если третий аргумент не указан, по умолчанию принимается значение netpath . Допустимые значения третьего аргумента такие же, как для аргумента nettype в API clnt create (см. раздел 12.3.1).

Заголовок msg2.h определяется пользователем и содержит только объявление RPC-номеров программы, версии и процедуры для функции printmsg;.

* Please do not edit this file.

* It was generated using rpcgen. */

#ifndef MSG2 H RPCGEN ♦define MSG2 H RPCGEN

♦ikclude <rpc/rpc.h>

♦define MSGPROG ((unsigned long)(0x20000001))

♦deq.ne MSGVER ((unsigned long)(l))

♦define PRINTMSG ((unsigned long)(1))

♦endif /* ! MSG H RPCGEN */

Программа RPC-сервера, соответствующая вышеупомянутой клиентской программе, называется msg svc2.C:

/* программа-сервер: низкоуровневые API RPC */ /* вызов: msg svc2 <механизм транспортировки> */

♦include <fstream.h> ♦include <stdlib.h> ♦include msg2.h ♦include RPC.h

RPC svc *svcp;

int printmsg( SVCXPRT* xtrp )

int res = 0; chr *msg =0;

if (svcp->getargs( xtrp, (xdrproc t)xdr string, ( cadd!5 t) smsg) !=>RPC SUCCESS)

return -1;

ofstream ofs( /dev/console ); if (ofs)

ofs server: msg Лп ; else res = -1;

if (svcp->reply(xtrp, (xdrproc t)xdr int, (caddr t)Sres)!-RPC SUCCESS) res - -2;

return res;

int main(int argc, char* argv[])

RPC svc *svcp = new RPC svc( MSGPROG, MSGVER, argc==2 ?

argv[l] : netpath );

if (svcp && svcp->run func( PRINTMSG, printmsg )) return 2;

return 0; /* сюда программа переходит только в том случае, если создание обработчика сервера завершается неудачно */



1 ... 73 74 75 [ 76 ] 77 78 79 ... 98

© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки.
Яндекс.Метрика