|
Программирование >> Структура ядра и системные вызовы
Клиент clnt <create RPC handle> clnt <create authentication> Сервер svc <create RPC handle> clnt call SVC run svc getargs svc send reply Рис 12 1. Клиентские и серверные API удаленных вызовов процедур и последовательность их вызова Клиентский API Назначение clnt create clnt tp create clnt tli create Задает базовый класс транспортных протоколов, которые будут использоваться во время выполнения Задает конкретный транспортный протокол Задает конечную точку транспортировки TLI, а те размеры передающего и принимающего буферов для RPC-связи. Описание TLI создается в клиентской программе Надписью clnt <create authentication> обозначен набор API RPC, каждый из которых создает запись данных аутентификации, используемых RPC-cep-вером для аутентификации клиента. Эти API не обязательны и нужны только в том случае, если RPC-серверу требуется контроль доступа. Пользователи могут создавать собственные схемы аутентификации для RPC-связи между клиентом и сервером и собственные функции RPC-аутентификации для своих программ. Ниже перечислены стандартные функции RPC-аутентификации для клиентских программ. Клиентский API authnone create authsys create default authdes seccreate Назначение Запись данных аутентификации содержит значение NULL. Вызывающий RPC-серверне должен требовать аутентификации клиента Запись данных аутентификации выполняется по методу управления доступом процессов, принятому в UNIX System V Запись данных аутентификации, зашифрованных по методу DES Интерфейс clnt со вызывает RPC-сервер для выполнения РС-програм-мы с заданным номером процедуры. Этот вызов включает входной аргумент И его XDR-функцию, а также адрес переменной, которая принимает возвращаемое значение, и ее XDR-функцию. На стороне сервера svc <create RPCJiandle> обозначает набор API RPC, каждый из которых создает интерфейс к RPC-серверу, используемый для ответа на клиентские RPC-запросы. Эти API различаются по степени детализации при указании сетевого транспортного протокола, используемого для связи с RPC-клиентами. Перечислим их. Серверный API Назначение svc create Задает базовый класс транспортных протоколов, которые вы- бираются ю время выполнения svc tp create Задает конкретный транспортный протокол svc tli create Залает конечную точку транспортировки TLI, а также размеры передающего и принимающего буферов для RPC-связи. Описание TLI создается в серверной профамме API svc run вызывается после того, как сервер создаст обработчик вызовов RPC. Эта функция входит в бесконечный цикл и ждет поступления клиентских RPC-запросов. Для обслуживания каждого вызова она активизирует указанную пользователем функцию-диспетчер. Эту функцию можно заменить пользовательской функцией, особенно если фебуется, чтобы сервер, когда он не занят обслуживанием запросов, выполнял какие-нибудь другие операции. Функция-диспетчер вызывает API svc getargs, извлекающий аргументы RPC-функции, которая передана из клиентского процесса. Затем она вызывает затребованную RPC-функцию и с помощью API svc sendreply передает возвращенное этой функцией значение клиенту. Синтаксис этих API описан в следующих разделах. В разд. 12.5 рассматриваются два класса RPC, которые инкапсулируют низкоуровневые API удаленных вызовов процедур. Эти классы предоставляют пользователям упрошенный интерфейс профаммирования RPC, позволяя в то же время управлять механизмами RPC-фанспортировки и памятью, используемой XDR-функциями для обработки данных. 12.5. Классы RPC В данном разделе рассматриваются два класса RPC: один используется для построения RPC-сервера, а другой - для построения RPC-клиента. Эти классы позволяют разработчикам приложений работать с высокоуровневым RPC-интерфейсом, избавляя их от необходимости подробно изучать API удаленных вызовов процедур ONC и UNIX System V. Более того, пользователи могут создавать из этих RPC-классов собственные подклассы, объекты рРЫх могут хранить больше данных, чем обработчики RPC-сервера и *<РС-клиентов, и обеспечивают дополнительные функции (например, вызов Предварительно определенных процедур при поступлении запросов и реализацию широковещательного режима). Применение классов RPC создает дополнительные удобства и расширяет возможности пользователей: Классы RPC скрывают различия между API, построенными по методу ONC, и API, построенными по методу UNIX System V.4. Поэтому приложения, в которых используются эти классы, можно переносить на большинство коммерческих UNIX-систем. При создании RPC-приложений затрачивается меньше времени на обучение и программирование. Пользователи получают возможность сконцентрировать основные усилия на разработке базовых клиентских и серверных функций. Таким же достоинством, как вы помните, обладает компилятор rpcgen. Пользователи могут модифицировать классы RPC для управления используемыми механизмами RPC-транспортировки и методами аутентификации, а также для динамического распределения памяти, применяемой XDR-функциями. В приведенном ниже заголовке RPC.h определены два класса RPC, которые инкапсулируют клиентские и серверные API RPC. tifndef RPC H #define RPC H /.----------------------------------------------------- /* Определение заголовка для RPC-классов /.----------------------------------------------------- -*/ */ -*/ tinclude <iostream.h> #ifdef cplusplus extern C { #endif tinclude <stdio.h> tinclude <stdlib.h> tinclude <string.h> tinclude <unistd.h> tinclude <time.h> tinclude <sys/types.h> tifdef SYSV4 tinclude <rpc/rpc.h> tinclude <rpc/svc soc.h> tinclude <rpc/pmap clnt.h> tinclude <netconfig.h> telse /* ONC */ ♦include <rpc/rpc.h> tinclude <rpc/pmap clnt.h> tinclude <sys/socket.h> tinclude <netdb.h> tinclude <utmp.h> tdefine AUTH SYS AUTH UNIX tdefine AUTH SHORT AUTH UNIX tendif tifdef cplusplus tendif tdefine UNDEF PROGNUM 0x0 tdefine TCP BUFSIZ 4098 typedef int (*rpcprog)(SVCXPRT*); typedef struct { unsigned prgnum; unsigned vernum; unsigned prcnum; rpcprog func; ) RPCPROG INFO; /.------------------------------------------------------ /* Класс RPC-сервера /.--------------------------------..... ......--------- class RPC svc ( int rc; unsigned prgnum, vernum; static RPCPROG INFO* progList; static int numProg; SVCXPRT *svcp; public: /* Программа-диспетчер */ static void dispatch( struct svc req* rqstp, SVCXPRT *xport ) ♦ifdef SYSV4 if (rqstp->rq proc==NULLPROC} { svc sendreply(xport, (xdrproc t)xdr void, 0); return ; uid t uid = 0; gid t gid = 0, gids[20]; short len = 0; switch (rqstp->rq cred.oa flavor) { . . , case AUTH NONE: break; case AUTH SYS: ( struct authsys parms* authp; authp = (struct authsys parms*)rqstp->rq clntcred; ♦else #endif #ifdef SYSV4 #ifdef SOLARIS 25 ♦else ♦endif struct authunix parms* authp; л authp = (struct authunix j5arms*)rqstp->rq clntcred; uid = authp->aup uid; gid = authp->aup gid; break; case AUTH DES: ( if (!authdes getucred( (struct authdes cred*)rqstp->rq clntcred, suid, &gid, Slen, (long*)gids)) &uid, Sgid, Slen, (Int*)gids)) ♦endif cerr decode DES auth. record failedXn ; svcerr systemerr(xport); return; } break; default: svcerr wea)cauth (xport) ; return; if (uid != getuidO && uid!a (uid t) 0) ( cerr client (uid= uid ) authentication failsXn ; svcerr wea)cauth (xport) ; return; int i; for ( 1=0; i < RPC svc::numProg; i++) if (RPC svc: :progList(i] .prcnuin==rqstp->rq j)roc && RPC svc::progList[i].vernuin==rqstp->rq vers && RPC svc: :progList(i] .prgnuin==rqstp->rq prog) if ((*RPC svc::progList[i].func)(xport)!=RPC SUCCESS) cerr rpc server execute prog rqstp->rq proc failsXn ; breajc; if (i >= RPC svc::numProg) svcerr noproc(xport); /* Функция-конструктор. Создает объект RPC-сервера для заданного номера и версии программы */ RPC svc( unsigned prognum, unsigned versnum, const char* nettype) ♦ifdef SYSV4 rc=svc create(dispatch, prognum, versnum, nettype); if (!rc) cerr Cant create ROC server for prog: prognum endl; else prgnum = prognum, vernum = versnum; svcp = 0; ♦else int proto = 0; if (nettype && !strcmp(nettype, tcp )) svcp=svctcp create(RPC ANYSOCK, TCP BUFSIZ, TCP BUFSIZ); proto = IPPROTO TCP; } else svcp=svcudp create(RPC ANYSOCK); proto = IPPROTO UDP; if (Isvcp) ( rc = 0; cerr Cant create RPC server for prog: prognum endl } else { rc = 1; prgnum = prognum, vernum = versnum; pmap unset( prognum, versnum ); if (!svc register(svcp, prognum, versnum, dispatch, proto)) ( cerr could not register RPC program/ver: prognum / versnum endl; rc = 0; ♦endif ); /* Создать обработчик сервера для обратного вызова */ RPC svc( int fd, char* transport, u long progno, u long versno ) ♦ifdef SYSV4 struct netconfig *nconf = getnettJOiffigent(transport) ; if (! nconf) f,; cerr invalid transport: transport endl; rc = 0; ; JOil Ь1й return;
|
© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки. |