UNIX: взаимодействие процессов
Шрифт:
8. Чтобы проверить это, изменим код одного из серверов (скажем, из листинга 15.6) так, чтобы он вызывал door_revoke из процедуры сервера. Поскольку аргументом door_revoke является дескриптор двери, его придется сделать глобальным. Вот что получится при запуске клиента (из листинга 15.1) два раза подряд:
Первый вызов
9. Чтобы не делать дескриптор fd глобальным, мы воспользуемся указателем cookiе, который можем передать door_create и который затем будет передаваться процедуре сервера при каждом вызове. В листинге Г.10 приведен текст сервера.
Мы легко могли бы изменить листинги 5.17 и 5.18, поскольку указатель cookie доступен функции my_thread (через структуру door_info_t), которая передает указатель на эту структуру создаваемому потоку (которому нужно знать дескриптор для вызова door_bind).
10. В этом примере атрибуты потока не меняются, поэтому их достаточно инициализировать лишь единожды (в функции main).
Глава 16
1. Программа отображения портов (port mapper) не проверяет серверы на работоспособность во время регистрации. После завершения сервера отображения остаются в силе, в чем мы можем убедиться с помощью пpoгрaммы rpcinfо. Поэтому клиент, связывающийся с программой отображения портов, получит информацию, которая была
2. Библиотека RPC возвращает первый ответ сервера клиенту сразу по получении, то есть через 20 секунд после вызова клиента. Следующий ответ будет храниться в сетевом буфере для данной конечной точки до тех пор, пока эта точка не будет закрыта или не будет выполнена операция чтения из нее библиотекой RPC. Предположим, что клиент отправит второй вызов серверу сразу после получения первого ответа. Если потерь в сети не произойдет, следующей прибывшей дeйтaгрaммoй будет ответ сервера на повторно переданную клиентом дейтаграмму. Но библиотека RPC проигнорирует этот ответ, поскольку XID будет совпадать с первым вызовом процедуры, который не может быть равным XID для второго вызова.
3. Соответствующая структура в С — это char c[10], но она будет закодирована XDR как десять 4-байтовых целых. Если вы хотите использовать строку фиксированной длины, используйте скрытый тип данных фиксированной длины.
4. Вызов xdr_data возвращает FALSE, поскольку вызов xdr_string (прочитайте содержимое файла data_xdr.c) возвращает FALSE.
Максимальная длина строки указывается в качестве последнего аргумента xdr_string. Если максимальная длина не указана, этот аргумент принимает значение 0 в дополнительном коде (2³²–1 для 32-разрядного целого).
5. Пoдпpoгрaммы XDR проверяют наличие достаточного объема свободной памяти в буфере для кодирования данных и возвращают ошибку FALSE при переполнении буфера. К сожалению, отличить одну ошибку от другой для подпpoгрaмм XDR невозможно.
6. В принципе, можно сказать, что использование последовательных номеров в TCP для обнаружения повторов эквивалентно кэшу повторных запросов, поскольку эти последовательные номера позволяют обнаружить любой устаревший сегмент. Для конкретного соединения (IP-адреса и порта клиента) размер этого кэша соответствует половине 32-разрядного последовательного номера TCP, то есть 2³¹ или 2 Гбайт.
7. Поскольку все пять значений для конкретного запроса должны в точности равняться пяти значениям в кэше, первое сравнение должно выполняться для того поля, которое может отличаться с наибольшей вероятностью. Реальный порядок сравнений в пакете TI-RPC таков: (1) XID, (2) номер процедуры, (3) номер версии, (4) номер программы, (5) адрес клиента. Разумно сравнивать XID в первую очередь, поскольку именно это значение меняется от запроса к запросу.
8. На рис. 16.5 имеется двенадцать 4-байтовых полей, начиная с поля флага и длины и включая 4 байта на аргумент типа long. Получается 48 байт. При использовании нулевой аутентификации данные о пользователе и проверочные данные будут отсутствовать. При этом они займут по 8 байтов: 4 байта на тип аутентификации (AUTH_NONE) и 4 байта на длину аутентификационных данных (0).