Главная страница  Взаимодействие нетривиальных процессов 

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 [ 146 ] 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186

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>: /* массив переменной длины с одним элементом */ продолжение



1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 [ 146 ] 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186

© 2000 - 2024 ULTRASONEX-AMFODENT.RU.
Копирование материалов разрешено исключительно при условии цититирования.