Чтение онлайн

ЖАНРЫ

UNIX: взаимодействие процессов

Стивенс Уильям Ричард

Шрифт:

В листинге 16.22 приведен текст заголовочного файла, созданного программой rpcgen из файла opt2.х.

Листинг 16.22. Заголовочный файл, созданный программой rpcgen

//sunrpc/xdr1/opt2.h

7 struct mylist {

8 char *name;

9 long value;

10 struct mylist *next;

11 };

12 typedef struct mylist mylist;

13 struct args {

14 mylist *list;

15 };

16 typedef struct args args;

В

листинге 16.23 приведен текст программы, инициализирующей связный список с тремя парами имя-значение и кодирующей его с помощью библиотеки XDR.

Листинг 16.23. Инициализация, кодирование связного списка и вывод результата

1 //sunrpc/xdr1/opt2.c

2 #include "unpipc.h"

3 #include "opt2.h"

4 int

5 main(int argc, char **argv)

6 {

7 int i;

8 XDR xhandle;

9 long *lptr;

10 args out; /* структура, которую мы заполняем */

11 char *buff; /* результат кодирования */

12 mylist nameval[4]; /* до четырех элементов в списке */

13 size_t size;

14 out.list = &nameval[2]; /* [2] –> [1] –> [0] */

15 nameval[2].name = "name1";

16 nameval[2].value = 0x1111;

17 nameval[2].next = &nameval[1];

18 nameval[1].name = "namee2";

19 nameval[1].value = 0x2222;

20 nameval[1].next = &nameval[0];

21 nameval[0].name = "nameee3";

22 nameval[0].value = 0x3333;

23 nameval[0].next = NULL;

24 buff = Malloc(BUFFSIZE); /* адрес должен быть кратен 4 */

25 xdrmem_create(&xhandle, buff, BUFFSIZE, XDR_ENCODE);

26 if (xdr_args(&xhandle, tout) != TRUE)

27 err_quit("xdr_args error");

28 size = xdr_getpos(&xhandle);

29 lptr = (long*)buff;

30 for (i = 0; i < size; i += 4)

31 printf("%8lx\n", (long)ntohl(*lptr++));

32 exit(0);

33 }

Инициализация связного списка

11-22 Мы выделяем память под четыре элемента, но инициализируем только три из них. Первая запись nameval[2], потом nameval[1] и nameval[0]. Указатель на начало списка (out.list) устанавливается на &nameval[2]. Мы инициализируем список в таком порядке, чтобы показать, что библиотека XDR обрабатывает указатели и порядок в списке оказывается именно таким, каким он был в нашей программе, и не зависит от того, какие массивы для этого используются. Мы также инициализируем значения элементов списка шестнадцатеричными величинами, поскольку будем выводить их в этом формате.

Вывод программы показывает,

что перед каждым элементом списка идет значение 1 в 4 байтах (что мы можем считать длиной массива переменной длины с одним элементом или булевским значением TRUE). Четвертая запись состоит из 4 байт, в которых записан 0. Она обозначает конец списка:

solaris % opt2

1 дальше идет один элемент

5 длина строки

6e616d65 имя(name)

31000000 1 и три байта дополнения

1111 значение

1 один элемент

6 длина строки

6e616d65 имя

65320000 е 2 и 2 байта дополнения

2222 значение

1 один элемент

7 длина строки

6e616d65 имя

65653300 е е 3 и 1 байт дополнения

3333 значение

0 конец списка

При декодировании списка библиотека XDR будет динамически выделять память под его элементы и указатели и связывать все это вместе, что позволит легко переходить от одного элемента списка к другому в программе на С.

16.9. Форматы пакетов RPC

На рис. 16.5 приведен формат запроса RPC в пакете TCP.

Поскольку TCP передает поток байтов и не предусматривает границ сообщений, приложение должно предусматривать способ разграничения сообщений. Sun RPC определяет запись как запрос или ответ, и каждая запись состоит из одного или более фрагментов. Каждый фрагмент начинается с 4-байтового значения: старший бит является флагом последнего фрагмента, а следующие 31 бит представляют собой счетчик (длина фрагмента). Если бит последнего фрагмента имеет значение 0, данный фрагмент не является последним в записи.

ПРИМЕЧАНИЕ

Это 4-байтовое значение передается в порядке big-endian, так же как и 4-байтовые целые в XDR, но оно не относится к стандарту XDR, поскольку он не предусматривает передачи битовых полей.

Если вместо TCP используется UDP, первое поле в заголовке UDP будет идентификатором транзакции (XID), как показано на рис. 16.7.

ПРИМЕЧАНИЕ

При использовании TCP на размер запроса и ответа RPC ограничения не накладываются, поскольку может использоваться любое количество фрагментов, а длина каждого из них задается 31-разрядным целым. Но при использовании протокола UDP запрос (и ответ) должен помещаться в дейтаграмму целиком, а максимальное количество данных в ней — 65507 байт (для IPv4). Во многих реализациях, предшествовавших TI-RPC, размер ограничивался значением около 8192 байт, поэтому если требуется передавать более 8000 байт, следует пользоваться протоколом TCP.

Поделиться с друзьями: