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():

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);

}

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


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