Читать «UNIX: взаимодействие процессов» онлайн - страница 278
Уильям Ричард Стивенс
//sunrpc/square5/client.c
1 #include "unpipc.h"
2 #include "square.h"
3 int
4 main(int argc, char **argv)
5 {
6 CLIENT *cl;
7 square_in in;
8 square_out *outp;
9 struct timeval tv;
10 if (argc != 4)
11 err_quit("usage: client <hostname> <integer-value> <protocol>");
12 cl = Clnt_create(argv[1], SQUARE_PROG, SQUARE_VERS, argv[3]);
13 Clnt_control(cl, CLGET_TIMEOUT, (char*)&tv);
14 printf("timeout = %ld sec, %ld usec\n", tv.tv_sec, tv.tv_usec);
15 if (clnt_control(cl, CLGET_RETRY_TIMEOUT, (char *) &tv) == TRUE)
16 printf("retry timeout = %ld sec, %ld usec\n", tv.tv_sec, tv.tv_usec);
17 in.arg1 = atol(argv[2]);
18 if ((outp = squareproc_1(&in, cl)) == NULL)
19 err_quit("%s", clnt_sperror(cl, argv[1]));
20 printf(result: %ld\n", outp->res1);
21 exit(0);
22 }
Используемый протокол является аргументом командной строки
10-12 Теперь протокол, являющийся последним аргументом clnt_create, указывается в качестве нового параметра командной строки.
Получение значения общего тайм-аута
13-14 Первым аргументом clnt_control является дескриптор клиента, вторым — тип запроса, а третьим — указатель на буфер. Наш первый запрос имеет значение CLGET_TIMEOUT; при этом возвращается значение общего тайм-аута в структуре timeval, адрес которой передается третьим аргументом. Этот запрос корректен для всех протоколов.
Попытка получения тайм-аута повтора
15-16 Следующий запрос имеет значение CLGET_RETRY_TIMEOUT. При этом должно возвращаться значение тайм-аута повтора, но этот запрос корректен только для протокола UDP. Следовательно, если функция возвращает значение FALSE, мы ничего не печатаем.
Изменим также и программу-сервер, добавив в нее ожидание продолжительностью 1000 секунд вместо 5, чтобы гарантировать получение тайм-аута по запросу клиента. Запустим сервер на узле bsdi, а клиент запустим дважды, один раз указав в качестве протокола TCP, а другой — UDP. Результат будет не таким, как мы ожидали:
solaris % date ; client bsdi 44 tcp ; date
Wed Apr 22 14:46:57 MST 1998
timeout = 30 sec, 0 usec
bsdi: RPC: Timed out
Wed Apr 22 14:47:22 MST 1998
solaris % date ; client bsdi 55 udp ; date
Wed Apr 22 14:48:05 MST 1998
timeout = –1 sec, –1 usec
retry timeout = 15 sec, 0 usec
bsdi: RPC: Timed out
Wed Apr 22 14:48:31 MST 1998
В случае с протоколом TCP значение тайм-аута, возвращенное clnt_control, было 30 секунд, но библиотека возвратила ошибку через 25 секунд. Для протокола UDP было получено значение общего тайм-аута –1.
Чтобы понять, что тут происходит, изучим текст заглушки клиента — функции squareproc_1 в файле square_clnt.c, созданном rpcgen. Эта функция вызывает библиотечную функцию с именем clnt_call, причем последним аргументом является структура типа timeval с именем TIMEOUT, объявляемая в этом файле, и инициализируется она значением 25 секунд. Этот аргумент clnt_call отменяет значение общего тайм-аута в 30 секунд для TCP и –1 для UDP. Он используется всегда, если клиент не устанавливает общий тайм-аут явно вызовом clnt_control с запросом CLSET_TIMEOUT. Если мы хотим изменить значение общего тайм-аута, следует вызывать clnt_control, а не изменять содержимое заглушки клиента.