Главная страница Взаимодействие нетривиальных процессов 42 } 43 xdr free(xdr data. (char *) &in); 44 exitCO): 45 } Выделение правильно расположенного буфера 11-13 Вызывается функция mal 1ос для выделения буфера. В этот буфер считывается файл, созданный предыдущей программой. Создание потока XDR, инициализация буфера, декодирование 14-17 Инициализируем поток XDR, указав флаг XDR DECODE, означающий, что преобразование производится из формата XDR в формат узла. Мы инициализируем структуру i п нулями и вызываем xdr data для декодирования содержимого буфера buff в эту структуру. Мы обязаны инициализировать принимающую структуру нулями, поскольку некоторые из подпрограмм XDR (например, xdr string) требуют выполнения этого условия. xdr data - это та же функция, которую мы вызывали в листинге 16.13. Изменился только последний аргумент xdrmem create: в предыдущей программе мы указывали XDR ENCODE, а в этой - XDR DECODE. Это значение сохраняется в дескрипторе XDR (xhandl е) функцией xdrmem create и затем используется библиотекой XDR для выбора между кодированием и декодированием данных. Вывод значений полей структуры 1В-42 Мы выводим значения всех полей структуры data. Освобождение выделенной под XDR памяти 43 Для освобождения памяти мы вызываем функцию xdr free (см. упражнение 16.10). Запустим программу write на компьютере Sparc, перенаправив стандартный вывод в файл с именем data: Solaris % write > data Solaris % Is -1 data -rw-rw-r-- 1 rstevens otherl 76 Apr 23 12:32 data Мы видим, что размер файла равен 72 байтам что соответствует рис. 16.4, на котором изображена схема хранения данных. Прочитав этот файл в BSD/OS или Digital Unix, мы получим те результаты, на которые и рассчитывали: bsdi % read < data read 76 bytes short arg = 1, long arg = 2. vstring arg = hello, world fopaque[] =99. BB. 77 vopaqueo = 33 44 fshort arg[] = 9999, BBBB. 7777, 6666 vlongo = 123456 234567 34567B uarg (int) = 123 short long string <128> < opaque [3] opaque <> short [4] long <> , Г ion < L I union enum int 123456 234567 345678 Рис. 16.4. Формат потока XDR, записанный в листинге 16.13 alpha % read < data read 76 bytes short arg = 1. long arg = 2, vstring arg = hello, world fopaque[] = 99. BB, 77 vopaqueo = 33 44 fshort arg[] = 9999, BBBB, 7777, 6666 vlongo = 123456 234567 34567B uarg (int) = 123 Пример: вычисление размера буфера в предыдущем примере мы выделяли буфер размера BUFFSIZE (определенного в файле unpi рс. h в листинге В. 1), и этого было достаточно. К сожалению, не существует простого способа вычислить объем памяти, нужный XDR для кодирования конкретных данных. Вычислить размер структуры вызовом sizeof недостаточно, потому что каждое поле кодируется XDR по отдельности. Нам придется перебирать элементы структуры, прибавляя к конечному результату объем памяти, нужный XDR для кодирования очередного элемента. В листинге 16.15 приведен пример простой структуры с тремя полями. Листинг 16.15. Спецификация XDR для простой структуры sunrpc/xdrl/examplе.X 1 const МАХС = 4; struct example ( short а: double b; 5 short с[МАХС]; 6 }: Программа, текст которой приведен в листинге 16.16, вычисляет размер буфера, требуемого XDR для кодирования этой структуры. Он получается равным 28 байт. Листинг 16.16. Программа, вычисляющая размер буфера XDR sunrpc/xdrl/example.c 1 #include unpipc.h 2 #include example.h 3 int 4 mainCint argc. char **argv) 6 int size: 7 example foo: 8 size - RNDUP(sizeof(foo.a)) + RNDUPCsizeof(foo.b)) + 9 RNDUP(sizeof(foo.c[0])) * MAXC: 10 printf( size = %й\п . size): 11 exitCO); 12 } B-9 Макрос RNDUP определен в файле <rpc/xdr.h>. Он округляет аргумент к ближайшему кратному BYTES PER XDR UNIT (4). Для массива фиксированного размера вычисляется размер каждого элемента, который затем умножается на количество элементов. Проблема возникает в случае использования типов данных переменной длины. Если мы объявим string d<10>, максимальный размер будет RNDUP(sizeof (1 nt)) (для длины) плюс RNDUP(sizeof(char)*10) (для символов строки). Но мы не можем вычислить размер буфера, если максимальный размер не указан в объявлении переменной (например, f 1 oat е<>). Лучше всего в этом случае выделять буфер с запасом, а потом проверять, не возвращают ли подпрограммы XDR ошибку (упражнение 16.5). Пример: необязательные данные Существуют три способа задания необязательных данных в файле XDR, примеры для всех приведены в листинге 16.17. Листинг 16.17. Файл спецификации XDR, иллюстрирующий способы задания необязательных данных sunrpc/xdrl/optl.x 1 union optlong switch (bool flag) { 2 case TRUE: 3 long val; 4 case FALSE; 5 void: 6 }: 7 struct args { 8 optlong argl; /* объединение с булевским дискриминантом */ 9 long arg2<l>: /* массив переменной длины с одним элементом */ продолжение
|
© 2000 - 2024 ULTRASONEX-AMFODENT.RU.
Копирование материалов разрешено исключительно при условии цититирования. |