Пусть приложение работает на отдельном компьютере, и его необходимо преобразовать, чтобы использовать в "распределенной" сети. Ниже показано пошаговое преобразование программы, которая выводит сообщения на терминал.
Однопроцессная версия printmesg.c:
#include <stdio.h>
main(int argc, char *argv[])
{
char *message;
if (argc != 2) {
fprintf(stderr, "usage: %s <message>\n",argv[0]);
exit(1);
}
message = argv[1];
if (!printmessage(message)) {
fprintf(stderr,"%s: невозможно вывести сообщение\n",
argv[0]); exit(1);
}
printf("Сообщение выведено!\n");
exit(0);
}
/* Вывод сообщения на терминал.
* Возвращает логическое значение, показывающее
* выведено ли сообщение. */
printmessage(char *msg) {
FILE *f;
f = fopen("/dev/console", "w");
if (f == (FILE *)NULL) return (0);
fprintf(f, "%s\n", msg);
fclose(f);
return(1);
}
Если функцию printmessage() превратить в удаленную процедуру, ее можно вызывать на любой машине сети.
Сначала необходимо определить типы данных всех аргументов вызова процедуры и результата. Аргумент вызова printmessage() представляет собой строку, а результат - целое число. Теперь можно написать спецификацию протокола на языке RPC, который будет описывать удаленную версию printmessage(). Исходный код RPC для данной спецификации:
program MESSAGEPROG {
version PRINTMESSAGEVERS {
int PRINTMESSAGE(string) = 1;
} = 1;
} = 0x20000001;
В этом примере PRINTMESSAGE - это процедура номер 1 в версии 1 удаленной программы MESSAGEPROG с номером программы 0x20000001.
Номера версии увеличиваются, если в удаленной программе изменяются функциональные возможности. При этом могут быть заменены существующие процедуры или добавлены новые. Может быть определена более чем одна версия удаленной программы, а также каждая версия может иметь более одной определенной процедуры.
Необходимо разработать еще две дополнительные программы. Одной из них является сама удаленная процедура. Версия printmsg.c для RPC:
* msg_proc.c: реализация удаленной процедуры
* "printmessage" */
#include <stdio.h>
#include "msg.h" /* msg.h сгенерированный rpcgen */
int * printmessage_1(char **msg, struct svc_req *req) {
static int result; /* должен быть static! */
FILE *f;
f = fopen("/dev/console", "w");
if (f == (FILE *)NULL) {
result = 0;
return (&result);
}
fprintf(f, "%s\n", *msg);
fclose(f);
result = 1;
return (&result);
}
При этом определение удаленной процедуры printmessage_1 отличается от локальной процедуры printmessage в следующих моментах:
* rprintmsg.c: удаленная версия "printmsg.c"
*/
#include <stdio.h>
#include "msg.h" /* msg.h сгенерирован rpcgen */
main(int argc, char **argv)
{
CLIENT *clnt;
int *result;
char *server;
char *message;
if (argc != 3) {
fprintf(stderr, "usage: %s host
message\n", argv[0]);
exit(1);
}
server = argv[1];
message = argv[2];
/*
* Создает клиентский "обрабочик", используемый
* для вызова MESSAGEPROG на сервере
*/
clnt = clnt_create(server, MESSAGEPROG,
PRINTMESSAGEVERS, "visible");
if (clnt == (CLIENT *)NULL) {
/*
* Невозможно установить соединение с сервером.
*/
clnt_pcreateerror(server);
exit(1);
}
/*
* Вызов удаленной процедуры
* "printmessage" на сервере
*/
result = printmessage_1(&message, clnt);
if (result == (int *)NULL) {
/*
* Ошибка при вызове сервера
*/
clnt_perror(clnt, server);
exit(1);
}
/* Успешный вызов удаленной процедуры.
*/
if (*result == 0) {
/*
* Сервер не может вывести сообщение.
*/
fprintf(stderr, "%s: невозможно вывести
сообщение\n", argv[0]);
exit(1);
}
/* Сообщение выведено на терминал сервера
*/
printf("Сообщение доставлено %s\n", server);
clnt_destroy( clnt );
exit(0);
}
Следует отметить следующие особенности клиентской программы вызова printmsg.c:
Для компиляции примера удаленного rprintmsg:
В этом примере не было создано никаких процедур XDR, потому что приложение использует только основные типы, которые включены в libnsl. Теперь нужно рассмотреть, что создано rpcgen на основе входного файла msg.x: