Читать «UNIX: взаимодействие процессов» онлайн - страница 263
Уильям Ричард Стивенс
//sunrpc/square1/square.x
1 struct square_in { /* входные данные (аргумент) */
2 long arg1;
3 };
4 struct square_out { /* возвращаемые данные (результат) */
5 long res1;
6 };
7 program SQUARE_PROG {
8 version SQUARE_VERS {
9 square_out SQUAREPROC(square_in) = 1; /* номер процедуры = 1 */
10 } = 1; /* номер версии */
11 } = 0x31230000; /* номер программы */
Файлы с расширением .х называются файлами спецификации RPC. Они определяют процедуры сервера, их аргументы и возвращаемые значения.
Определение аргумента и возвращаемого значения
1-6 Мы определяем две структуры — одну для аргументов (одно поле типа long) и одну для результатов (тоже одно поле типа long).
Определение программы, версии и процедуры
7-11 Мы определяем программу RPC с именем SQUARE_PROG, состоящую из одной версии (SQUARE_VERS), а эта версия представляет собой единственную процедуру сервера с именем SQUAREPROC. Аргументом этой процедуры является структура square_in, а возвращаемым значением — структура square_out. Мы также присваиваем этой процедуре номер 1, как и версии, а программе мы присваиваем 32-разрядный шестнадцатеричный номер. (О номерах программ более подробно говорится в табл. 16.1.)
Компилировать спецификацию нужно программой rpcgen, входящей в пакет Sun RPC.
Теперь напишем функцию main клиента, который будет осуществлять удаленный вызов процедуры. Текст программы приведен в листинге 16.2.
Листинг 16.2. Функция main клиента, делающего удаленный вызов процедуры
//sunrpc/square1/client.c
1 #include "unpipc.h" /* наш заголовочный файл */
2 #include "square.h" /* создается rpcgen */
3 int
4 main(int argc, char **argv)
5 {
6 CLIENT *cl;
7 square_in in;
8 square_out *outp;
9 if (argc != 3)
10 err_quit("usage: client <hostname> <integer-value>");
11 cl = Clnt_create(argv[1], SQUARE_PROG, SQUARE_VERS, "tcp");
12 in.arg1 = atol(argv[2]);
13 if ((outp = squareproc_1(&in, cl)) == NULL)
14 err_quit("ls", clnt_sperror(cl, argv[1]));
15 printf("result: %ld\n", outp->res1);
16 exit(0);
17 }
Подключение заголовочного файла, создаваемого rpcgen
2 Мы подключаем заголовочный файл square.h, создаваемый функцией rpcgen.
Объявление дескриптора клиента
6 Мы объявляем дескриптор клиента (client handle) с именем cl. Дескрипторы клиентов выглядят как обычные указатели на тип FILE (поэтому слово CLIENT пишется заглавными буквами).
Получение дескриптора клиента
11 Мы вызываем функцию clnt_create, создающую клиент RPC:
#include <rpc/rpc.h>
CLIENT *clnt_create(const char
/* Возвращает ненулевой дескриптор клиента в случае успешного завершения. NULL – в случае ошибки */
Как и с обычными указателями на тип FILE, нам безразлично, на что указывает дескриптор клиента. Скорее всего, это некоторая информационная структура, хранящаяся в ядре. Функция clnt_create создает такую структуру и возвращает нам указатель на нее, а мы передаем его библиотеке RPC времени выполнения каждый раз при удаленном вызове процедуры.