next up previous contents
Next: Разработка высокоуровневых приложений RPC. Up: Удаленный вызов процедур. Previous: Серверная часть.   Contents

Передача произвольных типов данных

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

Доступны следующие примитивные процедуры XDR для обработки типов данных:

xdr_int() xdr_netobj() xdr_u_long() xdr_enum()

xdr_long() xdr_float() xdr_u_int() xdr_bool()

xdr_short() xdr_double() xdr_u_short() xdr_wrapstring()

xdr_char() xdr_quadruple() xdr_u_char() xdr_void()

Непримитивная xdr_string(), которая принимает больше чем два параметра, вызывается из xdr_wrapstring().

В случае собственной процедуры программиста, структура

struct simple {

  int a;

  short b;

} simple;

содержит аргументы вызова процедуры. Процедура xdr_simple() преобразует структуру аргумента так , как показано ниже:

#include <rpc/rpc.h>

#include "simple.h"

bool_t xdr_simple(XDR *xdrsp, struct simple *simplep)

{

  if (!xdr_int(xdrsp, &simplep->a))

    return (FALSE);

  if (!xdr_short(xdrsp, &simplep->b))

    return (FALSE);

  return (TRUE);

}

Эквивалентную процедуру можно создать автоматически с помощью rpcgen.

Процедура XDR возвращает результат, отличный от нуля, если она завершается успешно, либо 0 в случае ошибки.

Для более сложных структур данных используют готовые процедуры XDR.

xdr_array() xdr_bytes() xdr_reference()

xdr_vector() xdr_union() xdr_pointer()

xdr_string() xdr_opaque()

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

struct varintarr {

  int *data;

  int arrlnth;

} arr;

Массив транслируется через xdr_array(), как показано ниже:

bool_t xdr_varintarr(XDR *xdrsp, struct varintarr *arrp)

{

  return(xdr_array(xdrsp, (caddr_t)&arrp->data, 

  (u_int *)&arrp->arrlnth, MAXLEN, sizeof(int), xdr_int));

}

Аргументы xdr_array() - обработчик XDR, указатель на массив, указатель на размер массива, максимальный размер массива, размер каждого элемента массива, и указатель на процедуру XDR для преобразования каждого элемента массива. Если размер массива известен заранее, более эффективным является использование xdr_vector():

int intarr[SIZE];

bool_t xdr_intarr(XDR *xdrsp, int intarr[])

{

  return (xdr_vector(xdrsp, intarr, SIZE, sizeof(int), xdr_int));

}

При сериализации XDR преобразует величины к четырехбайтным значениям. Для массивов символов каждый символ занимает 32 бита. xdr_bytes() упаковывает символы. Он имеет четыре параметра, схожие с первыми четырьмя параметрами функции xdr_array().

Строки, законченные пустым указателем, транслируются с помощью xdr_string(). Она сходна с xdr_bytes(), но без параметра длины. При сериализации процедура получает длину строки из strlen(), а при десериализации создает законченную пустым указателем строку.

xdr_reference() вызывает встроенные функции xdr_string() и xdr_reference(), которые преобразуют указатели, для передачи строки, и struct simple из предыдущего примера. Пример использования xdr_reference() (рис. 37):

struct finalexample {

  char *string;

  struct simple *simplep;

} finalexample;

 

bool_t xdr_finalexample(XDR *xdrsp, struct finalexample *finalp)

{

  if (!xdr_string(xdrsp, &finalp->string, MAXSTRLEN))

    return (FALSE);

  if (!xdr_reference( xdrsp, &finalp->simplep, sizeof(struct simple),

    xdr_simple)) return (FALSE);

  return (TRUE);

}

Рис. 37. Пример использования xdr_reference().

Процедура thatxdr_simple(), должна вызываться вместо xdr_reference().



2003-12-09