27-33
Если указатель ptr
установлен, значит, был указан параметр маршрутизации от отправителя, и все указанные промежуточные узлы добавляются к маршруту, подготовленному на предыдущем этапе функцией inet_srcrt_add
. Если же ptr
не установлен, но в командной строке еще есть аргументы, значит, пользователь задал маршрут, но не указал его тип. В этом случае программа завершает работу с сообщением об ошибке.
Обработка адреса получателя и создание сокета
34-35
Последний аргумент командной строки — это имя узла или адрес сервера в точечно-десятичной записи, который обрабатывается нашей функцией host_serv
. Мы не можем вызвать функцию tcp_connect
, так как должны задать маршрут от отправителя между вызовом функций socket
и connect
. Последняя инициирует трехэтапное рукопожатие, а нам нужно, чтобы сегмент SYN отправителя и все последующие пакеты проходили по одному и тому же маршруту.
36-42
Если маршрут от отправителя задан, следует добавить IP-адрес сервера в конец списка адресов (см. рис. 27.1). Функция setsockopt
устанавливает маршрут от отправителя для данного сокета. Затем мы вызываем функцию connect, а потом — нашу функцию str_cli
(см. листинг 5.4).
Наш TCP-сервер имеет много общего с кодом, показанным в листинге 5.9, но содержит следующие изменения.
Во-первых, мы выделяем место для параметров:
int len;
u_char *opts;
opts = Malloc(44);
Во-вторых, мы получаем параметры IP после вызова функции accept
, но перед вызовом функции fork
:
len = 44;
Getsockopt(connfd, IPPROTO_IP, IP_OPTIONS, opts, &len);
if (len > 0) {
printf("received IP options, len = %d\n", len);
inet_srcrt_print(opts, len);
}
Если сегмент SYN, полученный от клиента, не содержит никаких параметров IP, переменная len
по завершении функции getsockopt
будет иметь нулевое значение (эта переменная относится к типу «значение-результат»). Как уже упоминалось, нам не нужно предпринимать какие-либо шаги для того, чтобы на стороне сервера использовался обращенный маршрут от отправителя: это делается автоматически без нашего участия [128, с. 931]. Вызывая функцию getsockopt
, мы просто получаем копию обращенного маршрута от отправителя. Если мы не хотим, чтобы TCP использовал этот маршрут, то после завершения функции accept следует вызвать функцию setsockopt
и задать нулевую длину (последний аргумент), тем самым удалив все используемые в текущий момент параметры IP. Но маршрут от отправителя тем не менее уже был использован в процессе трехэтапного рукопожатия при пересылке второго сегмента. Если мы уберем параметры маршрутизации, IP составит и будет использовать для пересылки последующих пакетов какой-либо другой маршрут.
Теперь мы покажем пример клиент-серверного взаимодействия при заданном маршруте от отправителя. Мы запускаем наш клиент на узле freebsd
следующим образом:
freebsd4 % tcpcli01 -g macosx freebsd4 macosx
Тем самым дейтаграммы IP отсылаются с узла freebsd
на узел macosx
, обратно на узел freebsd4
, и наконец, на macosx
, где запущен наш сервер. Две промежуточные системы freebsd4
и macosx
должны переправлять дейтаграммы и принимать дейтаграммы с маршрутизацией от отправителя, чтобы этот пример работал.
Когда соединение устанавливается, на стороне сервера выдается следующий результат:
macosx % tcpserv01
received IP options, len = 16
received LSRR, 172.24.37.94 172.24.37.78 172.24.37.94
Первый выведенный IP-адрес — это первый узел обратного маршрута ( freebsd4
, как показано на рис. 27.2), а следующие два адреса идут в том порядке, который используется сервером для отправки дейтаграмм назад клиенту. Если мы понаблюдаем за процессом взаимодействия клиента и сервера с помощью программы tcpdump
, мы увидим, как используется параметр маршрутизации для каждой дейтаграммы в обоих направлениях.
ПРИМЕЧАНИЕ
К сожалению, действие параметра сокета IP_OPTIONS никогда не было документировано, поэтому вы можете увидеть различные вариации поведения в системах, не происходящих от исходного кода Беркли. Например, в системе Solaris 2.5 первый адрес, возвращаемый функцией getsockopt (см. рис. 27.2) — это не первый адрес в обращенном маршруте, а адрес собеседника. Тем не менее обратный маршрут, используемый TCP, будет корректен. Кроме того, в Solaris 2.5 всем параметрам маршрутизации предшествует четыре параметра NOP, что ограничивает параметр маршрутизации восемью IP-адресами, а не девятью, которые реально могли бы поместиться.
Читать дальше
Конец ознакомительного отрывка
Купить книгу