Dest | IfIndex | NextHop | Type | Proto | Mask |
0.0.0.0 | 2 | 140.252.1.183 | непрямой (4) | другой (1) | 0.0.0.0 |
127.0.0.1 | 3 | 127.0.0.1 | прямой (3) | другой (1) | 255.255.255.255 |
140.252.1.183 | 2 | 140.252.1.29 | прямой (3) | другой (1) | 255.255.255.255 |
140.252.13.32 | 1 | 140.252.13.33 | прямой (3) | другой (1) | 255.255.0.0 |
140.252.13.65 | 1 | 140.252.13.35 | непрямой (4) | другой (1) | 255.255.255.255 |
Для сравнения здесь приводится таблица маршрутизации IP в формате вывода команды netstat (см. главу 9, раздел "Принципы маршрутизации"). На рисунке 25.24 таблица маршрутизации приводится в лексикографическом порядке:
sun % netstat -rn
Routing tables
Destination Gateway Flags Refcnt Use Interface
140.252.13.65 140.252.13.35 UGH 0 115 le0
127.0.0.1 127.0.0.1 UH 1 1107 lo0
140.252.1.183 140.252.1.29 UH 0 86 sl0
default 140.252.1.183 UG 2 1628 sl0
140.252.13.32 140.252.13.33 U 8 68359 le0
И последняя таблица для группы ip это таблица трансляции адресов, приведенная на рисунке 25.25. Как мы говорили раньше, группа at в настоящее время практически не используется (как устаревшая), и эта таблица заменяет ее.
Таблица трансляции IP адресов, индекс = <ipNetToMediaIfIndex>.<ipNetToMediaNetAddress> | |||
Имя | Тип данных | R/W | Описание |
ipNetToMediaIfIndex | INTEGER | · | Соответствующий интерфейс: ifIndex. |
ipNetToMediaPhysAddress | PhysAddress | · | Физический адрес. |
ipNetToMediaNetAddress | IpAddress | · | IP адрес. |
ipNetToMediaType | [1..4] | · | Тип сопоставления: 1=другой, 2=неиспользуемый, 3=динамический, 4=статический. |
Количество строк в этой таблице не определяется SNMP, однако мы увидим, что менеджер, используя оператор get-next (раздел "Простые примеры" этой главы), может определить, что получена последняя строка таблицы. Также, в разделе "Примеры идентификации" мы увидим, как менеджер указывает, какую строку таблицы он хочет получить или установить.
Мы еще увидим этот порядок колонка-строка, когда будем использовать оператор get-next в следующем разделе.
Давайте посмотрим эту таблицу на системе sun. Мы показали только часть таблицы, так как очень много серверов (в данном случае слушающие процессы) слушает запросы на соединения. Перед тем как получить таблицу, было установлено два TCP соединения:
sun % rlogin gemini IP адрес gemini равен 140.252.1.11
и
sun % telnet localhost IP адрес должен быть 127.0.0.1
Единственный слушающий сервер, как мы показали, это FTP сервер на порте 21:
sun % snmpi -a sun dump tcpConnTable
tcpConnState.0.0.0.0.21.0.0.0.0.0=listen(2)
tcpConnState.127.0.0.1.23.127.0.0.1.1415=established(5)
tcpConnState.127.0.0.1.1415.127.0.0.1.23=established(5)
tcpConnState.140.252.1.29.1023.140.252.1.11.513=established(5)
tcpConnLocalAddress.0.0.0.0.21.0.0.0.0.0=0.0.0.0
tcpConnLocalAddress.127.0.0.1.23.127.0.0.1.1415=127.0.0.1
tcpConnLocalAddress.127.0.0.1.1415.127.0.0.1.23=127.0.0.1
tcpConnLocalAddress.140.252.1.29.1023.140.252.1.11.513=140.252.1.29
tcpConnLocalPort.0.0.0.0.21.0.0.0.0.0=21
tcpConnLocalPort.127.0.0.1.23.127.0.0.1.1415=23
tcpConnLocalPort.127.0.0.1.1415.127.0.0.1.23=1415
tcpConnLocalPort.140.252.1.29.1023.140.252.1.11.513=1023
tcpConnRemAddress.0.0.0.0.21.0.0.0.0.0=0.0.0.0
tcpConnRemAddress.127.0.0.1.23.127.0.0.1.1415=127.0.0.1
tcpConnRemAddress.127.0.0.1.1415.127.0.0.1.23=127.0.0.1
tcpConnRemAddress.140.252.1.29.1023.140.252.1.11.513=140.252.1.11
tcpConnRemPort.0.0.0.0.21.0.0.0.0.0=0
tcpConnRemPort.127.0.0.1.23.127.0.0.1.1415=1415
tcpConnRemPort.127.0.0.1.1415.127.0.0.1.23=23
tcpConnRemPort.140.252.1.29.1023.140.252.1.11.513=513
Для команды rlogin на хост gemini присутствует только один пункт, так как gemini это удаленный хост. Мы видим только клиентскую часть соединения (локальный порт 1023), однако показаны оба конца Telnet соединения (порт клиента 1415 и порт сервера 23), так как соединение проходит через loopback интерфейс. Также мы можем видеть, что слушающий FTP сервер имеет локальный IP адрес 0.0.0.0, что указывает на то, что он примет соединение с любого интерфейса.
sun % snmpi -a kinetics -c secret dump at
atIfIndex.1.1.140.252.1.4=1
atIfIndex.1.1.140.252.1.22=1
atIfIndex.1.1.140.252.1.183=1
atIfIndex.2.1.140.252.6.4=2
atIfIndex.2.1.140.252.6.6=2
atPhysAddress.1.1.140.252.1.4=0xaa:00:04:00:f4:14
atPhysAddress.1.1.140.252.1.22=0x08:00:20:0f:2d:38
atPhysAddress.1.1.140.252.1.183=0x00:80:ad:03:6a:80
atPhysAddress.2.1.140.252.6.4=0x00:02:16:48
atPhysAddress.2.1.140.252.6.6=0x00:02:3c:48
atNetAddress.1.1.140.252.1.4=140.252.1.4
atNetAddress.1.1.140.252.1.22=140.252.1.22
atNetAddress.1.1.140.252.1.183=140.252.1.183
atNetAddress.2.1.140.252.6.4=140.252.6.4
atNetAddress.2.1.140.252.6.6=140.252.6.6
С использованием tcpdump можно увидеть следующее. Для того чтобы получить полную таблицу, snmpi, во-первых, выдает get-next для имени таблицы (at в данном примере), чтобы получить первый пункт. Затем печатает первый пункт и выдает get-next. Это продолжается до тех пор, пока не будет получена вся таблица целиком.
На рисунке 25.20 показана подобная таблица.
atIfIndex | AtPhysAddress | atNetAddress |
1 | 0xaa:00:04:00:f4:14 | 140.252.1.4 |
1 | 0x08:00:20:0f:2d:38 | 140.252.1.22 |
1 | 0x00:80:ad:03:6a:80 | 140.252.1.183 |
2 | 0x00:02:16:48 | 140.252.6.4 |
2 | 0x00:02:3c:48 | 140.252.6.6 |
Здесь мы приводим ARP кэш системы sun:
sun % arp -a
svr4 (140.252.13.34) at 0:0:c0:c2:9b:26
bsdi (140.252.13.35) at 0:0:c0:6f:2d:40
и соответствующий SNMP вывод:
sun % snmpi -a sun dump ipNetToMediaTable
ipNetToMediaIfIndex.1.140.252.13.34=1
ipNetToMediaIfIndex.1.140.252.13.35=1
ipNetToMediaPhysAddress.1.140.252.13.34=0x00:00:c0:c2:9b:26
ipNetToMediaPhysAddress.1.140.252.13.35=0x00:00:c0:6f:2d:40
ipNetToMediaNetAddress.1.140.252.13.34=140.252.13.34
ipNetToMediaNetAddress.1.140.252.13.35=140.252.13.35
ipNetToMediaType.1.140.252.13.34=dynamic(3)
ipNetToMediaType.1.140.252.13.35=dynamic(3)
Рассмотрим идентификацию пунктов таблицы более подробно. Давайте вернемся к таблице слушающего процесса UDP (рисунок 25.7).
Для каждой таблицы в MIB указан один или несколько индексов. Для таблицы слушающего процесса UDP, MIB определяет индекс как комбинацию двух переменных udpLocalAddress (локальный IP адрес) и udpLocalPort (локальный UDP порт), индекс в данном случае - целое число. (Мы показали этот индекс в верхней строке на рисунке 25.9.)
Представьте себе, что в таблице слушающего процесса UDP есть три строки: первая для IP адреса 0.0.0.0 и порта 67, вторая для 0.0.0.0 и порта 161 и третья для 0.0.0.0 и порта 520. На рисунке 25.11 показана эта таблица.
udpLocalAddress | udpLocalPort |
0.0.0.0 | 67 |
0.0.0.0 | 161 |
0.0.0.0 | 520 |
Давайте обратимся к нашему обсуждению сортировки адресов, которая осуществляется DNS, приведенному в разделе "Простой пример" главы 14. Мы показали, как первый IP адрес, возвращенный DNS сервером, был одним из тех, что принадлежат к той же подсети, что и клиент. Также мы упомянули, что использование другого IP адреса, вполне возможно, будет работать, однако в этом случае все будет менее эффективно. Давайте посмотрим, что произойдет при использовании альтернативного IP адреса. Мы будем использовать SNMP, чтобы посмотреть пункты в таблице маршрутизации, и попробуем объединить вместе несколько концепций, о которых мы рассказывали в предыдущих главах и которые имели отношение к IP маршрутизации.
Хост gemini имеет несколько интерфейсов, два из которых Ethernet интерфейсы. Во-первых, убедимся, что можем получить соединение Telnet на оба адреса:
sun % telnet 140.252.1.11 daytime
Trying 140.252.1.11 ...
Connected to 140.252.1.11.
Escape character is '^]'.
Sat Mar 27 09:37:24 1993
Connection closed by foreign host.
sun % telnet 140.252.3.54 daytime
Trying 140.252.3.54 ...
Connected to 140.252.3.54.
Escape character is '^]'.
Sat Mar 27 09:37:35 1993
Connection closed by foreign host.
Мы видим, что нет никакой разницы в соединениях между двумя адресами. Сейчас воспользуемся traceroute, чтобы посмотреть, используются ли различные маршруты к каждому адресу:
sun % traceroute 140.252.1.11
traceroute to 140.252.1.11 (140.252.1.11), 30 hops max, 40 byte packets
1 netb (140.252.1.183) 299 ms 234 ms 233 ms
2 gemini (140.252.1.11) 233 ms 228 ms 234 ms
sun % traceroute 140.252.3.54
traceroute to 140.252.3.54 (140.252.3.54), 30 hops max, 40 byte packets
1 netb (140.252.1.183) 245 ms 212 ms 234 ms
2 swnrt (140.252.1.6) 233 ms 229 ms 234 ms
3 gemini (140.252.3.54) 234 ms 233 ms 234 ms
Мы видим, что при использовании адреса подсети 140.252.3 появляется дополнительная пересылка (маршрутизатор swnrt - это R3 на рисунке 3.6). Давайте посмотрим, почему осуществляется эта дополнительная пересылка.
На рисунке 25.29 показаны настройки систем. На основе вывода команды traceroute мы можем сказать, что хост gemini и маршрутизатор swnrt оба подсоединены к двум сетям: 140.252.1 и 140.252.3.
Когда тайм-аут возникает позже, через 5,802 секунды, текущий RTO рассчитывается следующим образом
RTO = A + 4D = 0 + 4 x 3 = 12 секунд
Затем к RTO равному 12 применяется экспотенциальное наращивание. Так как это первый тайм-аут, используется множитель 2, при этом значение следующего тайм-аута будет равно 24 секундам. Следующий тайм-аут рассчитывается с использованием множителя 4, значения тайм-аута становится 48 секунд: 12 x 4. (Эти исходные RTO для первого SYN, 6 секунд и затем 24 секунды, как раз то, что мы видели на рисунке 4.5.)
ACK прибывает через 467 миллисекунд после повторной передачи. Значения A и D не обновляются, потому что алгоритм Карна определяет двусмысленность передачи. Следующий отправляемый сегмент - это ACK в строке 4, однако время для него не засекается, так как это всего лишь подтверждение. (Время устанавливается только для сегментов, содержащих данные.)
Когда отправляется первый сегмент данных (сегмент 1 на рисунке 21.2), RTO не меняется, опять же в соответствии с алгоритмом Карна. Текущее значение, равное 24 секундам, повторно используется до тех пор, пока не будет осуществлено измерение RTT. Это означает, что RTO для момента времени равного 0 на рисунке 21.4 равно в действительности 24, однако мы не берем во внимание эту точку.
Когда прибывает подтверждение на этот первый сегмент данных (сегмент 2 на рисунке 21.2), получено 3 тика часов, и наши показатели устанавливаются следующим образом
A = M + 0,5 = 1,5 + 0,5 = 2
D = A/2 = 1
(Значение M равное 1,5 соответствует 3-м тикам часов.) Предыдущие установки A и D в 0 и 3 были сделаны для расчета первоначального RTO. Эти установки предназначены для первого расчета оценочных функций, с использованием первого измерения RTT M. RTO рассчитывается следующим образом
RTO = A + 4D = 2 + 4 x 1 = 6 секунд
Когда прибывает ACK на второй сегмент данных (сегмент 5 на рисунке 21.2), отсчитан 1 тик часов (0,5 секунды), и наши показатели обновляются следующим образом
Err = M - A = 0,5 - 2 = -1,5
A = A + gErr = 2 - 0,125 x 1,5 = 1,8125
D = D + h(|Err| - D) = 1 + 0,25 x (1,5 - 1) = 1,125
RTO = A + 4D = 1,8125 + 4 x 1,125 = 6,3125
Существует несколько тонкостей в представлении Err, A и D, при расчетах с фиксированной точкой, которая и используется в действительности (однако мы показали для простоты с плавающей точкой). Эта разница дает RTO равное 6 секундам (а не 6,3125), как раз столько, сколько было показано на рисунке 21.4 для момента времени 1,871.
Большинство Unix хостов может функционировать как NFS клиент и как NFS сервер, или как и то и другое одновременно. Большинство PC реализаций (MS-DOS) имеют только реализации NFS клиента. Большинство IBM мейнфреймов предоставляет только функции NFS сервера.
NFS в действительности - это нечто большее, чем просто NFS протокол. На рисунке 29.4 показаны различные программы RPC, которые используются с NFS.
Приложение | Номер программы | Номер версии | Количество процедур |
преобразователь портов | 100000 | 2 | 4 |
NFS | 100003 | 2 | 15 |
программа mount | 100005 | 1 | 5 |
менеджер блокирования | 100021 | 1,2,3 | 19 |
монитор статуса | 100024 | 1 | 6 |
Только первые три из приведенных приемлимы для MTA работающих по правилам RFC 821, так как в этих трех случаях генерируется содержимое тела сообщения в виде только NVT ASCII символов. При использовании расширенного SMTP с 8BITMIME, поддерживается 8bit кодирование.
Так как тип содержимого и кодирование независимы, RFC 1521 рекомендует quoted-printable для text с не-ASCII данными, и base64 для данных типа image, audio, video и octet-stream приложений. При этом гарантируется максимальная совместимость с MTA, работающими по правилам RFC 821. Типы содержимого multipart и message должны быть кодированы как 7bit.
На рисунке 28.8 показано почтовое сообщение, содержащее список распространяемых RFC, тип содержимого - multipart. Подтип - mixed, это означает, что каждая часть должна быть обработана последовательно, разделители между частями выглядят как строка NextPart, перед которой стоят два дефиса в начала строки.
За каждым разделителем может следовать строка, содержащая поля заголовка для следующей части. Часть сообщения перед первым разделителем игнорируется, так же как и часть следующая за последним разделителем.
Так как за первым разделителем следуют пустые строки и не указаны поля заголовка, между первым и вторым разделителями подразумевается тип содержимого данных text/plain с набором символов us-ascii. Это текстовое описание нового RFC.
За вторым разделителем, однако, следуют поля заголовков. Они определяют следующее сообщение как multipart, с разделителем OtherAccess. Подтип - alternative, причем присутствует два альтернативных варианта. Первый OtherAccess предназначен для получения RFC с использованием электронной почты, а второй для получения с использованием анонимного FTP. Пользовательский агент MIME предоставляет список из двух возможных вариантов, что позволяет автоматически получить копию RFC с использованием либо почты, либо анонимного FTP.
To: rfc-dist@nic.ddn.mil
Subject: RFC1479 on IDPR Protocol
Mime-Version: 1.0
Content-Type: Multipart/Mixed; Boundary="NextPart"
Date: Fri, 23 Jul 93 12:17:43 PDT
From: "Joyce K. Reynolds" <jkrey@isi.edu>
--NextPart первый разделитель
A new Request for Comments is now available in online RFC libraries.
. . . (здесь приводится описание нового RFC)
Below is the data which will enable a MIME compliant Mail Reader
implementation to automatically retrieve the ASCII version
of the RFCs.
--NextPart второй разделитель
Content-Type: Multipart/Alternative; Boundary="OtherAccess"
сообщение, состоящее из нескольких
частей с новым разделителем
--OtherAccess
Content-Type: Message/External-body;
access-type="mail-server";
server="mail-server@nisc.sri.com"
Content-Type: text/plain
SEND rfc1479.txt
--OtherAccess
Content-Type: Message/External-body;
name="rfc1479.txt";
site="ds.internic.net";
access-type="anon-ftp";
directory="rfc"
Content-Type: text/plain
--OtherAccess--
--NextPart-- последний разделитель
Мы можем увидеть некоторые ловушки с помощью tcpdump. Стартуем SNMP агента на системе sun и посмотрим, как он генерирует ловушку coldStart. (Агент знает о необходимости посылать ловушки на хост bsdi. Однако на bsdi не стартован менеджер для обработки ловушек, вместо него запущен tcpdump, что позволяет увидеть генерируемые пакеты. Обратитесь к рисунку 25.1, откуда видно, что ловушки посылаются от агента к менеджеру, однако менеджер не посылает подтверждений, поэтому нет необходимости, чтобы менеджер обрабатывал ловушки.) Затем, с использованием программы snmpi, мы посылаем запрос, в котором указано неверное имя сообщества. В ответ на это должна быть сгенерирована ловушка authenticationFailure. На рисунке 25.31 показан вывод.
1 0.0 sun.snmp > bsdi.snmp-trap: C=traps Trap(28)
E:unix.1.2.5 [140.252.13.33] coldStart 20
2 18.86 (18.86) sun.snmp > bsdi.snmp-trap: C=traps Trap(29)
E:unix.1.2.5 [140.252.13.33] authenticationFailure 1907
Сообщество (community) это строка символов, в которой содержится пароль в открытом виде. Пароль используется при общении между менеджером и агентом. Обычное значение - 6-символьная строка public.
В операторах get, get-next и set менеджер устанавливает идентификатор запроса (request ID), который возвращается агентом в сообщении get-response. Мы видели этот тип переменной в других UDP приложениях. (Вспомните поле идентификации (identification) DNS на рисунке 14.3 и поле идентификатора транзакции (transaction ID) на рисунке 16.2.) Это позволяет клиенту (менеджеру в данном случае) сопоставить отклики от сервера (агент) с запросами, которые были отправлены клиентом. Это поле также позволяет менеджеру выдать несколько запросов одному или нескольким агентам, а затем отсортировать полученные отклики.
Статус ошибки (error status) это целое число, которое возвращается агентам и указывает на ошибку. На рисунке 25.4 показаны значения, имена и описания ошибок.
статус ошибки | Имя | Описание |
0 | noError | все в порядке |
1 | tooBig | клиент не может поместить отклик в одно SNMP сообщение |
2 | noSuchName | оператор указывает на несуществующую переменную |
3 | badValue | в операции установки использовано недопустимое значение или сделана ошибка в синтаксисе |
4 | readOnly | менеджер попытался изменить переменную, которая помечена как "только для чтения" |
5 | genErr | неопознанная ошибка |
Мы установим соединение с хоста solaris (который поддерживает механизм определения транспортного MTU) на хост slip. Установки идентичны тем, которые использованы для примера определения транспортного MTU в случае UDP (рисунок 11.13), однако здесь мы установили MTU интерфейса на slip равный 552, вместо его обычного значения 296. Это заставляет slip объявить MSS равный 512. Мы оставили MTU = 296 на SLIP канале на bsdi, поэтому TCP сегменты, размером больше чем 256, должны быть фрагментированы. Посмотрим, как механизм определения транспортного MTU на solaris обработает подобную ситуацию.
Запустим программу sock на хосте solaris и осуществим одну запись величиной 512 байт на discard сервис хоста slip:
solaris % sock -i -n1 -w512 slip discard
На рисунке 24.2 мы показали вывод команды tcpdump, полученный на SLIP интерфейсе хоста sun.
Значение MSS в строках 1 и 2 как раз такое, как и ожидалось. Затем мы видим, что solaris отправил сегмент размером 512 байт (строка 3), содержащий 512 байт данных и подтверждение на SYN. (Мы видели эту комбинацию ACK вместе с SYN в первом сегменте данных в упражнении 9 главы 18.)
1 0.0 solaris.33016 > slip.discard: S 1171660288:1171660288(0)
win 8760 <mss 1460> (DF)
2 0.101597 (0.1016) slip.discard > solaris.33016: S 137984001:137984001(0)
ack 1171660289 win 4096
<mss 512>
3 0.630609 (0.5290) solaris.33016 > slip.discard: P 1:513(512)
ack 1 win 9216 (DF)
4 0.634433 (0.0038) bsdi > solaris: icmp:
slip unreachable - need to frag, mtu = 296 (DF)
5 0.660331 (0.0259) solaris.33016 > slip.discard: F 513:513(0)
ack 1 win 9216 (DF)
6 0.752664 (0.0923) slip.discard > solaris.33016: . ack 1 win 4096
7 1.110342 (0.3577) solaris.33016 > slip.discard: P 1:257(256)
ack 1 win 9216 (DF)
8 1.439330 (0.3290) slip.discard > solaris.33016: . ack 257 win 3840
9 1.770154 (0.3308) solaris.33016 > slip.discard:FP 257:513(256)
ack 1 win 9216 (DF)
10 2.095987 (0.3258) slip.discard > solaris.33016: . ack 514 win 3840
11 2.138193 (0.0422) slip.discard > solaris.33016: F 1:1(0) ack 514 win 4096
12 2.310103 (0.1719) solaris.33016 > slip.discard: . ack 2 win 9216 (DF)
Обратитесь к рисунку 4.6, где мы объясняли, как маршрутизатор netb использует уполномоченного агента ARP, для того чтобы создалось впечатление, как будто sun непосредственно подключен к Ethernet 140.252.1. В наших рассуждениях мы не принимаем во внимание модемы, которые включены в SLIP канал между sun и netb, так как это не влияет на наши рассуждения.
На рисунке 25.29 мы показали путь Telnet данных с использованием пунктирных стрелок, в том случае, когда был указан адрес 140.252.3.54. Как мы можем узнать, что возвращающиеся пакеты проходят непосредственно от gemini к netb, а не возвращаются тем же самым путем, по которому они пришли? Воспользуемся версией команды traceroute со свободной маршрутизацией от источника, которая описана в разделе "Опция IP маршрутизации от источника" главы 8:
sun % traceroute -g 140.252.3.54 sun
traceroute to sun (140.252.13.33), 30 hops max, 40 byte packets
1 netb (140.252.1.183) 244 ms 256 ms 234 ms
2 * * *
3 gemini (140.252.3.54) 285 ms 227 ms 234 ms
4 netb (140.252.1.183) 263 ms 259 ms 294 ms
5 sun (140.252.13.33) 534 ms 498 ms 504 ms
Когда используется свободная маршрутизация от источника, маршрутизатор swnrt никогда не отвечает. Если посмотреть на ранний вывод команды traceroute, без маршрутизации от источника, мы увидим, что swnrt является второй пересылкой. Причиной этого может являться то, что маршрутизатор не генерирует ICMP ошибки об истечении времени, когда в датаграмме установлена свободная маршрутизация от источника. Мы видим из этого вывода команды traceroute, что путь возврата от gemini (TTL 3, 4 и 5) проходит непосредственно к netb, а не проходит через маршрутизатор swnrt.
Вопрос, на который нам должен помочь ответить SNMP, заключается в том, что делает пункт таблицы маршрутизации в netb таким, что сеть назначения установлена в 140.252.3? Все дело в том, что netb отправляет пакеты к swnrt, а не непосредственно к gemini. Мы используем команду get, чтобы получить значение маршрутизатора следующей пересылки для этого пункта назначения:
sun % snmpi -a netb -c secret get ipRouteNextHop.140.252.3.0
ipRouteNextHop.140.252.3.0=140.252.1.6
Пункт таблицы маршрутизации говорит netb послать пакеты на swnrt, что, как мы видим, и происходит.
Почему gemini отправляет пакеты назад непосредственно через netb? Потому что адрес назначения для пакетов, возвращающихся от gemini, установлен в 140.252.1.29, а сеть 140.252.1 подключена непосредственно.
То, что мы видим в этом примере, является результатом политических решений о маршрутизации. Маршрут по умолчанию к сети 140.252.3 проходит через маршрутизатор swnrt, потому что gemini является просто хостом с несколькими интерфейсами, но не выполняет функции маршрутизатора. Это как раз пример хоста с несколькими интерфейсами, который не хочет быть маршрутизатором.
Первая информационная строка от локального MTA в примере была следующей: "Connecting to mailhost via ether".
Это объясняется тем, что система автора сконфигурирована таким образом, чтобы посылать всю нелокальную исходящую почту на транслирующую машину для дальнейшей доставки. Так сделано по двум причинам. Во-первых, упрощается конфигурацию всех MTA, кроме MTA транслирующей системы. (Конфигурация MTA не проста, каждый, кто когда-либо работал с Sendmail, может это подтвердить.) Во-вторых, одна система в организации может выступать в роли почтового ретранслятора, возможно пряча тем самым все остальные индивидуальные системы.
В нашем примере транслирующая система имеет имя хоста mailhost в локальном домене (.tuc.noao.edu), а все индивидуальные системы сконфигурированы таким образом, чтобы посылать свою почту на этот хост. Мы можем исполнить команду host, чтобы посмотреть, как это имя определено в DNS:
sun % host mailhost
mailhost.tuc.noao.edu CNAME noao.edu каноническое имя
noao.edu A 140.252.1.54 ее реальный IP адрес
Если хост, который используется в качестве ретранслирующего, в будущем изменится, необходимо только сменить его DNS имя - конфигурация почты всех индивидуальных систем не изменится.
Большинство организаций в настоящее время используют транслирующие системы. На рисунке 28.3 показана упрощенная схема почты в Internet (рисунок 28.2), причем сделано предположение, что большинство отправляющих хостов и окончательные получающие хосты используют транслирующие хосты.
Между отправителем и получателем присутствует четыре MTA. Локальный MTA на хосте отправителя просто доставляет почту на свой транслирующий MTA. (Этот транслирующий MTA должен иметь имя mailhost в домене организации.) Здесь SMTP использует локальные сети организации. Затем транслирующий MTA организации отправителя посылает почту по Internet на транслирующий MTA организации получателя. Другие транслирующие MTA доставляют почту на хост получателя после общения с локальными MTA хоста получателя. Все MTA в примере используют SMTP, хотя существует возможность того, что на этом пути могут встретиться и другие протоколы доставки.
Подобная форма, когда один сервер обрабатывает несколько клиентов, отличается от обычного TCP конкурентного сервера, который мы описали в разделе "Реализация TCP сервера" главы 18. FTP и Telnet серверы, например, запускают новый процесс каждый раз, когда приходит запрос на новое TCP соединение, поэтому каждый клиент общается со своим процессом сервера. В случае X, все клиенты, запущенные на этом же хосте или на другом хосте, общаются с одним сервером.
По TCP соединению между X клиентом и его сервером осуществляется обмен большим количеством данных. Количество данных зависит от конкретной реализации приложения. Например, если мы запустим клиента Xclock, который отображает текущее время и дату в окне клиента на сервере и укажем ему обновляться один раз в секунду, X сообщения посылаются по TCP соединению от клиента к серверу один раз в секунду. Если мы запустим эмулятор X терминала, Xterm, каждое нажатие клавиши будет генерировать 32-байтное X сообщение (72 байта вместе со стандартными IP и TCP заголовками), и еще больше X сообщений в обратном направлении с символами, отраженными эхом. [Droms and Dyksen 1990] рассчитывает TCP траффик между различными X клиентами и одним конкретным сервером.
Большинство Unix серверов также создают Unix domain сокет с именем /tmp/.X11-unix/Xn, где n это тот же номер дисплея.
Когда клиент стартует на другом хосте, он создает TCP конечную точку и осуществляет активное открытие на порт 6000 + n сервера. Каждый клиент имеет свое собственное TCP соединение с сервером. Уже от сервера будет зависеть, как он поделит ресурсы между всеми клиентами. Клиент отправляет по TCP соединению запросы на сервер (создает окно), сервер посылает обратно отклики, а также сервер посылает события клиенту (нажатие кнопки мыши, нажатие клавиш на клавиатуре, перемещение окна, изменение размера окна и так далее).
На рисунке 30.2 повторен рисунок 30.1, где показаны фазы общения клиента с процессом X сервера, которые, в свою очередь, обслуживают окна на дисплее. Здесь не показано, как X сервер обслуживает клавиатуру и мышь.
В этом примере сервер не выходит из строя, однако он недоступен в течение 10-минутного периода, когда отправляются пробы "оставайся в живых". Вполне возможно, что вышел из строя промежуточный маршрутизатор, телефонная линия может быть временно повреждена или произошло что-нибудь подобное.
Чтобы имитировать эту ситуацию, мы установили TCP соединение с нашего хоста slip через SLIP канал с дозвоном на хост vangogh.cs.berkeley.edu, а затем погасили канал. Во-первых, приведем вывод интерактивной сессии:
slip % sock -K vangogh.cs.berkeley.edu echo
testing вводим эту строку
testing строка отражена эхом
где-то в это время погашен SLIP канал
read error: No route to host
На рисунке 23.3 показан вывод команды tcpdump, который получен с маршрутизатора bsdi. (Установление соединения и объявления окна удалены.)
1 0.0 slip.1056 > vangogh.echo: P 1:9(8)ack1
2 0.277669 ( 0.2777) vangogh.echo > slip.1056: P 1:9(8)ack9
3 0.424423 ( 0.1468) slip.1056 > vangogh.echo: . ack 9
4 7200.818081 (7200.3937) slip.1056 > vangogh.echo: . ack 9
5 7201.243046 ( 0.4250) vangogh.echo > slip.1056: . ack 9
6 14400.688106 (7199.4451) slip.1056 > vangogh.echo: . ack 9
7 14400.689261 ( 0.0012) sun > slip: icmp: net vangogh unreachable
8 14475.684360 ( 74.9951) slip.1056 > vangogh.echo: . ack 9
9 14475.685504 ( 0.0011) sun > slip: icmp: net vangogh unreachable
14 строк удалено
24 15075.759603 ( 75.1008) slip.1056 > vangogh.echo: R 9:9(0)ack9
25 15075.760761 ( 0.0012) sun > slip: icmp: net vangogh unreachable
Давайте посмотрим, что произойдет, когда хост сервера вышел из строя и не перезагрузился. Чтобы имитировать эту ситуацию, мы поступим следующим образом: Установим соединение между клиентом (программа sock на хосте bsdi) и стандартным эхо сервером на хосте svr4. Клиент включает опцию "оставайся в живых" с помощью опции -K. Убедимся, что данные могут проходить по соединению. Посмотрим, что TCP модуль клиента отправляет пакеты "оставайся в живых" каждые 2 часа, и увидим, что они подтверждаются TCP модулем сервера. Отсоединим Ethernet кабель от сервера и оставим его отсоединенным до тех пор, пока пример не будет завершен. Это заставит клиента думать, что хост сервера вышел из строя. Мы ожидаем, что клиент отправит 10 проб "оставайся в живых" с интервалом в 75 секунд, перед тем как решит, что соединение умерло.
Здесь приводится интерактивный вывод клиента:
bsdi % sock -K svr4 echo опция -K для включения "оставайся в живых"
hello, world убедимся, что соединение работает
hello, world отражение эхом
отсоединяем Ethernet кабель после 4 часов
read error: Connection timed out это произошло примерно через 6 часов 10 минут после начала эксперимента
На рисунке 23.1 показан вывод tcpdump. (Мы удалили все посвященное установлению соединения и объявлению окна.)
1 0.0 bsdi.1055 > svr4.echo: P 1:14(13)ack 1
2 0.006105 ( 0.0061) svr4.echo > bsdi.1055: P 1:14(13)ack14
3 0.093140 ( 0.0870) bsdi.1055 > svr4.echo: . ack 14
4 7199.972793 (7199.8797) arp who-has svr4 tell bsdi
5 7199.974878 ( 0.0021) arp reply svr4 is-at 0:0:c0:c2:9b:26
6 7199.975741 ( 0.0009) bsdi.1055 > svr4.echo: . ack 14
7 7199.979843 ( 0.0041) svr4.echo > bsdi.1055: . ack 14
8 14400.134330 (7200.1545) arp who-has svr4 tell bsdi
9 14400.136452 ( 0.0021) arp reply svr4 is-at 0:0:c0:c2:9b:26
10 14400.137391 ( 0.0009) bsdi.1055 > svr4.echo: . ack 14
11 14400.141408 ( 0.0040) svr4.echo > bsdi.1055: . ack 14
12 21600.318309 (7200.1769) arp who-has svr4 tell bsdi
13 21675.320373 ( 75.0021) arp who-has svr4 tell bsdi
14 21750.322407 ( 75.0020) arp who-has svr4 tell bsdi
15 21825.324460 ( 75.0021) arp who-has svr4 tell bsdi
16 21900.436749 ( 75.1123) arp who-has svr4 tell bsdi
17 21975.438787 ( 75.0020) arp who-has svr4 tell bsdi
18 22050.440842 ( 75.0021) arp who-has svr4 tell bsdi
19 22125.432883 ( 74.9920) arp who-has svr4 tell bsdi
20 22200.434697 ( 75.0018) arp who-has svr4 tell bsdi
21 22275.436788 ( 75.0021) arp who-has svr4 tell bsdi
В этом примере мы увидим, что произойдет, если сервер выйдет из строя и перезагрузится. Первоначальный сценарий такой же как и раньше, однако после того, как мы убедились, что соединение функционирует, мы отсоединили сервер от Ethernet, перезагрузили его и затем вновь подсоединили его к Ethernet. Мы ожидаем, что следующая проба "оставайся в живых" сгенерирует сброс (reset) от сервера, потому что сервер сейчас ничего не знает об этом соединении. Ниже приводится интерактивная сессия:
bsdi % sock -K svr4 echo опция -K для включения "оставайся в живых"
hi there проверяем, что соединение функционирует
hi there это отражается эхом с удаленного конца
здесь сервер перезагружен, пока отсоединен кабель Ethernet
read error: Connection reset by peer
На рисунке 23.2 показан вывод команды tcpdump. (Мы удалили все связанное с установлением соединения и объявлением окна.)
1 0.0 bsdi.1057 > svr4.echo: P 1:10(9) ack 1
2 0.006406 ( 0.0064) svr4.echo > bsdi.1057: P 1:10(9) ack 10
3 0.176922 ( 0.1705) bsdi.1057 > svr4.echo: . ack 10
4 7200.067151 (7199.8902) arp who-has svr4 tell bsdi
5 7200.069751 ( 0.0026) arp reply svr4 is-at 0:0:c0:c2:9b:26
6 7200.070468 ( 0.0007) bsdi.1057 > svr4.echo: . ack 10
7 7200.075050 ( 0.0046) svr4.echo > bsdi.1057: R 1135563275:1135563275(0)
NFS был исходно написан, чтобы использовать UDP, и эту возможность предоставляют все производители. Однако, более новые реализации, также поддерживают TCP. Поддержка TCP используется для работы в глобальных сетях, которые становится все быстрее. Поэтому использование NFS в настоящее время уже не ограничено локальными сетями.
Границы между локальными и глобальными сетями стираются, и все это происходит очень быстро. Времена возврата меняются в очень широком диапазоне, и все чаще возникает переполнение. Эти характеристики глобальных сетей приводят к тому, что все чаще в них используются алгоритмы, которые мы рассматривали для TCP - медленный старт и избежание переполнения. Так как UDP не предоставляет ничего похожего на эти алгоритмы, то они или им подобные должны быть встроены в NFS клиент и сервер, иначе необходимо использовать TCP.
Как и в случае Rlogin клиента, Telnet клиент так же позволяет пообщаться с ним, вместо того чтобы отправлять пользовательский ввод серверу. Стандартный символ, позволяющий осуществить переход в режим управления клиентом (escape), это Control-] (control и правая квадратная скобка, что обычно печатается как "^]"). При этом клиент выводит приглашение, обычно выглядящее как "telnet>". В ответ на это приглашение можно вводить команды, что позволяет сменить характеристики сессии или напечатать какую-либо информацию. Команда help поддерживается большинством Unix клиентов и отображает все доступные команды.
Мы увидим примеры того, как можно управлять клиентом, а также как стоит пользоваться командами в следующем разделе.
По умолчанию управление потоком обычно осуществляет Rlogin клиент. Клиент распознает ASCII символы STOP и START (Control-S и Control-Q), которые вводятся пользователем, и останавливает или стартует вывод на терминал.
Если это не сделано, каждый раз, когда мы вводим Control-S, чтобы остановить вывод на терминал, символ Control-S отправляется по сети к серверу, и сервер прекращает писать в сеть, однако данные (размер данных может достигать размера окна) могут быть уже выданы сервером в сеть и будут отображены на терминале, перед тем как вывод будет остановлен. Сотни или тысячи байт данных могут прокрутиться на экране, перед тем как вывод будет остановлен. На рисунке 26.3 показан подобный сценарий.
Давайте, рассмотрим управление FTP соединением на примере простой FTP сессии, в течение которой просматривается список файлов на сервере. Клиент запущен на хосте svr4 с флагом -d (отладка). При этом печатаются команды и отклики, которыми происходит обмен по управляющему соединению. Все строки, начинающиеся с --->, отправляются клиентом серверу, а строки, которые начинаются с 3-циферных чисел, это отклики от сервера. Клиенту выдается приглашение в виде ftp>.
svr4 % ftp -d bsdi опция -d для отладочного вывода
Connected to bsdi. клиент осуществляет активное открытие управляющего соединения
220 bsdi FTP server (Version 5.60) ready. сервер отвечает, что он готов
Name (bsdi:rstevens): клиент спрашивает имя пользователя
---> USER rstevens вводим RETURN, поэтому используется имя по умолчанию
331 Password required for rstevens.
Password: вводим наш пароль; он не отображается эхом
---> PASS XXXXXXX клиент передает пароль в виде открытого текста
230 User rstevens logged in.
ftp> dir hello.c спрашиваем, находится ли в директории указанный файл
---> PORT 140,252,13,34,4,150 см. рисунок 27.4
200 PORT command successful.
---> LIST hello.c
150 Opening ASCII mode data connection for /bin/ls.
-rw-r--r-- 1 rstevens staff 38 Jul 17 12:47 hello.c
226 Transfer complete.
remote: hello.c вывод от клиента
56 bytes received in 0.03 seconds (1.8 Kbytes/s)
ftp> quit мы закончили
---> QUIT
221 Goodbye.
Когда FTP клиент просит нас ввести имя пользователя, он выводит имя по умолчанию (наше имя на хосте клиента). Когда мы нажимаем клавишу RETURN, отправляется это имя по умолчанию.
Когда мы спрашиваем, присутствует ли указанный файл в директории, устанавливается соединение данных. Этот пример является продолжением процедуры, показанной на рисунках 27.4 и 27.5. Клиент спрашивает свой TCP модуль о динамически назначаемом номере порта для своего конца соединения данных и отправляет этот номер порта (1174) серверу в виде команды PORT. Мы также видим, что одна команда, введенная пользователем (dir) генерирует две FTP команды (PORT и LIST).
На рисунке 27.6 приведена временная диаграмма, иллюстрирующая обмен пакетами по управляющему соединению. (Мы удалили все, что связано с установлением и прерыванием управляющего соединения, вместе со всеми объявлениями размера окна.) На этом рисунке показано как открывается соединение данных, используется и затем закрывается.
Если клиент не посылает команду PORT на сервер, чтобы указать номер порта для клиентской стороны соединения данных, сервер использует тот же номер порта для соединения данных, который был использован для управляющего соединения. Это может вызвать проблемы для клиента, который использует потоковый режим (который Unix FTP клиенты и сервера используют всегда), как мы покажем ниже.
Требование к хостам Host Requirements RFC рекомендует, чтобы FTP клиент использовал потоковый режим, посылая команду PORT, чтобы не использовать номер порта по умолчанию перед каждым использованием соединения данных.
Давайте снова обратимся к предыдущему примеру (рисунок 27.6). Что произойдет, если мы попробуем узнать содержимое другой директории через несколько секунд после того, как узнали содержимое первой? Клиент попросит свое ядро выбрать еще один динамически назначаемый порт (может быть, с номером 1175), после чего будет открыто следующее соединение данных между svr4 порт 1175 и bsdi порт 20. Однако на рисунке 27.7 сервер осуществляет активное закрытие соединения данных, и мы видели на рисунке 18.6, что сервер не в состоянии назначить порт 20 для нового соединения данных, так как считается, что локальный порта используется предыдущим соединением, пока находится в состоянии ожидания 2MSL.
Сервер обходит эту проблему, указывая опцию SO_REUSEADDR, которую мы упоминали в разделе "Диаграмма состояний передачи TCP" главы 18. Это позволяет ему назначить порт 20 для нового соединения, которое будет иметь другой номер удаленного порта (1175). В состоянии ожидания 2MSL находится порт 1174.
Однако процедура открытия соединения изменяется, если клиент не пошлет команду PORT, указывая динамически назначаемый номер порта клиента. Мы можем смоделировать подобную ситуацию, исполнив пользовательскую команду sendport на FTP клиенте. Unix FTP клиенты используют эту команду, чтобы выключить отправку команд PORT на сервер перед каждым использованием соединения данных.
На рисунке 27.8 показана временная диаграмма для соединений данных при использовании двух команд LIST. Управляющее соединение установлено от порта 1176 на хосте svr4, так что в случае отсутствия команды PORT клиент и сервер используют тот же самый номер порта для соединения данных. (Мы удалили объявления окна и значения типа сервиса.)
Тогда как Archie это индекс анонимных FTP серверов, Veronica это индекс заголовков пунктов Gopher. Veronica обычно осуществляет поиск по сотням Gopher серверов.
Чтобы получить доступ к Veronica, необходимо воспользоваться клиентом Gopher. Выберите пункт меню в Gopher "Beyond InterNIC: Virtual Treasures of the Internet", а затем выберите Veronica из следующего меню.
Время | Номер сегмента | Действие | Буфер приемника | |||
(рисунок 22.2) | Отправляющий TCP | Принимающий TCP | Приложение | данные | свободно | |
0,000 | 1 | 1:1025(1024) | 1024 | 3072 | ||
0,002 | 2 | 1025:2049(1024) | 2048 | 2048 | ||
0,003 | 3 | 2049:3073(1024) | 3072 | 1024 | ||
0,005 | 4 | 3073:4097(1024) | 4096 | 0 | ||
0,170 | 5 | ACK 4097, win 0 | ||||
3,99 | читает 256 | 3840 | 256 | |||
5,151 | 6 | 4097:4098(1) | 3841 | 255 | ||
5,17 | 7 | ACK 4098, win 0 | ||||
5,99 | читает 256 | 3585 | 511 | |||
7,99 | читает 256 | 3329 | 767 | |||
9,99 | читает 256 | 3073 | 1023 | |||
10,151 | 8 | 4098:4099(1) | 3074 | 1022 | ||
10,170 | 9 | ACK 4099, win 0 | ||||
11,99 | читает 256 | 2818 | 1278 | |||
13,99 | читает 256 | 2562 | 1534 | |||
15,151 | 10 | 4099:4100(1) | 2563 | 1533 | ||
15,170 | 11 | ACK 4100, win 1533 | ||||
15,172 | 12 | 4100:5124(1024) | 3587 | 509 | ||
15,370 | 13 | ACK 5124, win 509 | ||||
15,99 | читает 256 | 3331 | 765 | |||
17,99 | читает 256 | 3075 | 1021 | |||
19,99 | читает 256 | 2819 | 1277 | |||
20,151 | 14 | 5124:5633(509) | 3328 | 768 | ||
20,170 | 15 | ACK 5633, win 0 | ||||
21,99 | читает 256 | 3072 | 1024 | |||
23,99 | читает 256 | 2816 | 1280 | |||
25,151 | 16 | 5633:5634(1) | 2817 | 1279 | ||
25,170 | 17 | ACK 5634, win 1279 | ||||
25,171 | 18 | 5634:6145(511) | 3328 | 768 | ||
25,174 | 19 | ACK 6146, win 767 | ||||
25,99 | читает 256 | 3072 | 1024 | |||
27,99 | читает 256 | 2816 | 1280 | |||
29,99 | читает 256 | 2560 | 1536 | |||
31,99 | читает 256 | 2304 | 1792 | |||
33,99 | читает 256 | 2048 | 2048 | |||
35,99 | читает 256 | 1792 | 2304 | |||
37,99 | читает 256 | 1536 | 2560 | |||
39,99 | читает 256 | 1280 | 2816 | |||
39,99 | 20 | ACK 6146, win 2816 | ||||
41,99 | читает 256 | 1024 | 3072 | |||
43,99 | читает 256 | 768 | 3328 | |||
45,99 | читает 256 | 512 | 3584 | |||
47,99 | читает 256 | 256 | 3840 | |||
49,99 | читает 256 | 0 | 4096 | |||
51,99 | читает 256 (EOF) | 0 | 4096 | |||
51,991 | 21 | ACK 6146, win 4096 | ||||
51,992 | 22 | ACK 2 |
Требование к хостам Host Requirements RFC указывает, что IP команда должна быть послана с использованием сигнала синхронизации Telnet. Если это сделано, за <IAC, IP> должно следовать <IAC, DM>, с указателем срочности, указывающим на DM байт. Большинство Unix Telnet клиентов имеют опцию, которая отправляет IP команду с сигналом синхронизации, однако эта опция по умолчанию выключена (как мы здесь и видели).
Сегмент 2 это отклик сервера на опцию DO TIMING MARK. Он следует в сегментах 3 и 4 за сигналом синхронизации Telnet: <IAC, DM>. Указатель срочности в сегменте 3 указывает на DM байт, который отправляется в сегменте 4.
Если в очередь поставлено полное окно данных или оно в пути от сервера к клиенту, все эти данные будут отброшены клиентом после отправки команды прерывания процесса в сегменте 1. Даже если управление потоком данных TCP запретило серверу отправлять данные в сегментах 2, 3 и 4, указатель срочности все равно посылается. Это аналогично тому, что мы видели в случае Rlogin на рисунке 26.7.
Почему сигнал синхронизации посылается в виде двух сегментов (3 и 4)? Мы рассмотрели это в разделе "Режим срочности (Urgent Mode)" главы 20, это связано с указателем срочности TCP. Требование к хостам Host Requirements RFC говорит, что он должен указывать на последний байт срочных данных, тогда как большинство Berkeley реализаций указывают на 1 байт позади последнего байта срочных данных. (Обратитесь к рисунку 26.6, на котором указатель срочности указывает на 1 байт позади командного байта.) Сервер Telnet специально пишет первый байт сигнала синхронизации как срочные данные, зная, что указатель срочности будет (неверно) указывать на следующий байт, который он запишет (метка данных, DM), однако эта первая запись с байтом IAC посылается немедленно, вместе с указателем срочности, который следует в следующем сегменте за DM байтом.
Последний сегмент данных, сегмент 6, это следующее приглашение shellа от сервера.
Информационная база управления (MIB - Management Information Base) это информационная база данных, которая обслуживается агентом, а менеджер может запросить информацию из этой базы или записать информацию в эту базу. Мы рассмотрим то, что называется MIB-II и описано в RFC 1213 [McCloghrie and Rose 1991].
Как показано на рисунке 25.6, MIB поделена на группы: system, interfaces, at (трансляция адресов), ip и так далее.
В этом разделе мы опишем только переменные, находящиеся в группе UDP. Это простая группа с небольшим количеством переменных и одной таблицей. В следующих разделах, на примере этой группы мы покажем, как осуществляется идентификация, построение лексикографического порядка и некоторые простые примеры этих характеристик. После чего, в разделе "Информационная база управления (продолжение)", мы вернемся к MIB и опишем некоторые другие группы в MIB.
На рисунке 25.6 мы показали группу под названием udp, находящуюся ниже mib. На рисунке 25.7 показана структура группы UDP.
В строке 4 генерируется ICMP ошибка, и мы видим, что маршрутизатор bsdi генерирует новую ICMP ошибку, содержащую MTU исходящего интерфейса.
Так случилось, что перед тем, как эта ошибка вернулась на хост solaris, был отправлен FIN (строка 5). Так как slip не получил 512 байт данных, отброшенных маршрутизатором bsdi, и не ожидает этого номера последовательности (513), он отправляет ожидаемый номером последовательности (1) в строке 6.
В это время ICMP ошибка вернулась на solaris, и было повторно передано 512 байт данных в двух сегментах размером 256 байт (строки 7 и 9). Оба сегмента отправлены с установленным битом DF, так как дальше за маршрутизатором bsdi может быть еще один маршрутизатор, у которого MTU еще меньше.
Была осуществлена довольно долгая передача (она заняла примерно 15 минут), и после перехода от исходного размера сегмента равного 512 байт к сегментам размером 256 байт, solaris уже больше никогда не пытался отправить сегменты большего размера.
Во-первых, необходимо обратить внимание на то, что обе UDP датаграммы, отправленные от SNMP агента (порт 161, печатается как имя snmp), имеют порт назначения 162 (печатается как имя snmp-trap).
Выражение C=traps это имя сообщества в сообщении ловушки. Это опция конфигурации, которая используется агентом в случае ISODE SNMP.
Следующее выражение, Trap(28) в строке 1 и Trap(29) в строке 2, это тип PDU (PDU type) и длина.
Следующее поле вывода для обеих строк - E:unix.1.2.5. Это enterprise: идентификатор системы объекта (sysObjectID). Он находится под узлом 1.3.6.1.4.1 в дереве, приведенном на рисунке 25.6 (iso.org.dod.internet.private.enterprises), таким образом, идентификатор объекта агента равен 1.3.6.1.4.1.4.1.2.5. Его сокращенное имя unix.agents.fourBSD-isode.5. Последняя цифра (5) это номер версии релиза агента ISODE. Это значение указывает на то, какое программное обеспечение агента сгенерировало ловушку.
Следующее поле вывода команды tcpdump это IP адрес агента (140.252.13.33).
Тип ловушки печатается как coldStart в строке 1 и как authenticationFailure в строке 2. Они соответствуют значениям типа ловушки равным 0 и 4 соответственно (рисунок 25.30). Так как эти ловушки не являются специализированными (enterprise), специфичный код (specific code) должен быть равен 0 и поэтому не печатается.
Далее следует поле временной марки (timestamp), которое печатается как 20 и 1907. Это значение TimeTicks, соответствующее количеству сотых долей секунд с момента инициализации агента. В случае ловушки холодного старта, она генерируется через 200 миллисекунд после того, как агент инициализирован. Вывод tcpdump указывает на то, что вторая ловушка появилась через 18,86 секунды после первой, чему соответствует напечатанное значение 1907 сотых долей секунд минус 200 миллисекунд.
Из рисунка 25.2 видно, что сообщение ловушки может содержать переменные, которые агенты хотят отправить менеджеру, однако в наших примерах они не присутствуют.
Запрос о двух переменных посылается в одной UDP датаграмме, отклик также прибывает в одной UDP датаграмме.
Мы показали переменные в виде соответствующих им идентификаторов объектов, потому что именно это было отправлено в SNMP сообщениях. Мы должны были указать эти две переменные как 0. Обратите внимание на то, что в отклике всегда возвращается имя переменной (идентификатора объекта). Ниже мы увидим, что это необходимо для работы оператора get-next.
Archie помогает найти положение имен файлов, содержащих ключевые слова, однако иногда приходится искать файл или базу данных, ключевое слово в которой содержится внутри. Таким образом, осуществляется поиск файла, содержащего ключевое слово, а не имени файла, содержащего ключевое слово.
WAIS знает о сотнях баз данных, которые содержат информацию по темам, связанным с компьютерами, и другим общим темам. Чтобы использовать WAIS, мы выбираем базы данных для поиска и указываем ключевые слова. Чтобы попробовать WAIS, попробуйте подсоединиться Telnetом к quake.think.com с именем пользователя wais.
World Wide Web позволяет нам просмотреть в мировом масштабе большой набор сервисов и документов с использованием средства, которое называется гипертекст (hypertext). По мере того как информация отображается, определенные ключевые слова подсвечиваются, и мы можем получить более подробную информацию с использованием этих ключевых слов.
Чтобы получить доступ к WWW, подсоединитесь Telnetом к info.cern.ch.
X Window System, или просто X, это приложение клиент-сервер, которое позволяет нескольким клиентам (приложениям) использовать графический дисплей, управляемый сервером. Сервер это программное обеспечение, которое управляет дисплеем, клавиатурой и мышкой. Клиент это программа приложения, которая запущена либо на том же самом хосте, что и сервер, либо на другом хосте. В последнем случае обычная форма связи между клиентом и сервером это TCP, однако могут быть использованы и другие протоколы, такие как DECNET. В некоторых случаях сервер это часть аппаратного обеспечения (X терминал), которая общается с клиентом на другом хосте. В другом случае отдельно стоящая рабочая станция, клиент и сервер находятся на одном и том же хосте и общаются с помощью коммуникаций между процессами на этом хосте, без использования сетевого обеспечения. Однако наиболее стандартная ситуация, когда клиенты запущены на том же хосте, что сервер, или когда клиенты запущены на других хостах.
X требует надежный, двунаправленный потоковый протокол, такой как TCP. (X не разработана для работы с ненадежными протоколами, такими как UDP.) Общение между клиентом и сервером осуществляется посредством обмена 8-битовыми байтами по этому соединению. [Nye 1992] приводит формат более чем 150 сообщений, которыми обмениваются клиент и сервер по TCP соединению.
В Unix системах, когда X клиент и X сервер находятся на одном и том же хосте, вместо TCP обычно используются протоколы Unix domain, потому что в этом случае осуществляется меньше обработки протоколов, нежели при использовании с TCP. Протоколы Unix domain это форма общения между процессами, которая может быть использована между клиентами и серверами на одном и том же хосте. Обратитесь к рисунку 2.4, на котором видно, что когда TCP используется для общения между двумя процессами на одном и том же хосте, эти данные передаются по петле ниже IP уровня, при этом осуществляется обработка данных и TCP, и UDP. На рисунке 30.1 показан возможный вариант общения трех клиентов, использующих один дисплей. Один клиент на том же самом хосте, что и сервер, использует Unix domain протоколы. Остальные два клиента находятся на других хостах и используют TCP. Один клиент это обычно оконный менеджер (window manager), который имеет право располагать окна на дисплее. Оконный менеджер позволяет нам передвигать окна по экрану или, например, менять их размер.
На первый взгляд термины клиент и сервер не совсем уместны в данном случае. С такими приложениями как Telnet и FTP мы считаем, что клиент это интерактивный пользователь, который сидит за клавиатурой и дисплеем. Однако в случае X клавиатура и дисплей принадлежат самому серверу. Поэтому в данном случае сервер это то, что предоставляет сервис. Сервис, предоставляемый X, это доступ к окну, клавиатуре и мышке. В случае Telnet сервис это терминальный заход на удаленный хост. В случае FTP сервис это файловая система сервера.
X сервер обычно стартует, когда X терминал или рабочая станция загружаются. Сервер создает конечную точку TCP и осуществляет пассивное открытие на порт 6000 + n, где n это номер дисплея (обычно 0).
Представление внешних данных (XDR - External Data Representation) это стандарт, используемый для кодирования значений в RPC вызове и отклике сообщениях - полей заголовка RPC (XID, номер программы, статус приема и так далее), параметров процедуры и результатов процедуры. Стандартный способ кодирования данных позволяет клиенту вызвать процедуру в системе с отличной архитектурой. XDR определен в RFC 1014 [Sun Microsystems 1987].
XDR определяет определенное количество типов данных и точный способ того, как они передаются в RPC сообщении (порядок битов, порядок байтов и так далее). Отправитель должен построить RPC сообщение в XDR формате, тогда получатель конвертирует XDR формат в исходное представление. (В тот формат, который принят для его системы.) Мы видим, например, на рисунках 29.1 и 29.2, что все целые значения, которые мы показали (XID, вызов, номер программы и так далее), это 4-байтовые целые числа. И действительно, все целые в XDR занимают 4 байта. XDR поддерживает и другие типы данных, включая целые без знака, логические, числа с плавающей точкой, массивы фиксированной длины, массивы переменной длины и структуры.
В разделе "Записи ресурсов" главы 14 мы сказали, что один из типов записи ресурса в DNS используется для обмена почты и называется записями MX. В следующем примере мы покажем, как используются записи MX, для отправки почты на хосты, не подключенные к Internet непосредственно. RFC 974 [Partridge 1986] описывает, как MTA обрабатывает записи MX.
Хост mlfarm.com не подключен к Internet, однако имеет MX запись, указывающую на перенаправителя почты, который, в свою очередь, находится в Internet:
sun % host -a -v -t mx mlfarm.com
The following answer is not authoritative:
mlfarm.com 86388 IN MX 10 mercury.hsi.com
mlfarm.com 86388 IN MX 15 hsi86.hsi.com
Additional information:
mercury.hsi.com 86388 IN A 143.122.1.91
hsi86.hsi.com 172762 IN A 143.122.1.6
Здесь показаны две записи MX, каждая с различной степенью предпочтительности. Мы ожидаем, что MTA начнет с меньшего из двух значений предпочтительности.
Следующий скрипт показывает, как почта будет послана этому хосту:
sun % mail -v ron@mlfarm.com флаг -v, чтобы посмотреть, что делает MTA
To: ron@mlfarm.com
Subject: MX test message
здесь печатается тело сообщения (не показано)
. точка в конце строки завершает сообщение
Sending letter ... ron@mlfarm.com...
Connecting to mlfarm.com via tcp...
mail exchanger is mercury.hsi.com найдена запись MX
Trying 143.122.1.91... connected. делается первая попытка с минимальной предпочтительностью
220 mercury.hsi.com ...
здесь происходит обычная доставка почты SMTP
MTA определил, что хост назначения имеет MX запись и использует MX запись с минимальным значением предпочтительности.
Перед запуском этого примера на хосте sun была изменена конфигурация таким образом, чтобы при отправке почты не использовался обычный транслирующий хост, поэтому мы видим обмен почтой с хостом назначения. Также в конфигурации было сказано использовать DNS сервер на хосте noao.edu (к которому можно получить доступ через SLIP канал с дозвоном). Благодаря этому, с использованием tcpdump, мы можем посмотреть и передачу почты, и DNS траффик на SLIP канале. На рисунке 28.4 показана начальная часть вывода команды tcpdump.
1 0.0 sun.1624 > noao.edu.53: 2+ MX? mlfarm.com. (28)
2 0.445572 (0.4456) noao.edu.53 > sun.1624: 2* 2/0/2 MX
mercury.hsi.com. 10 (113)
3 0.505739 (0.0602) sun.1143 > mercury.hsi.com.25: S 1617536000:1617536000(0)
win 4096
4 0.985428 (0.4797) mercury.hsi.com.25 > sun.1143: S 1832064000:1832064000(0)
ack 1617536001 win 16384
5 0.986003 (0.0006) sun.1143 > mercury.hsi.com.25: . ack 1 win 4096
6 1.735360 (0.7494) mercury.hsi.com.25 > sun.1143: P 1:90(89) ack 1 win 16384
Rlogin использует одно TCP соединение между клиентом и сервером. После того как TCP соединение установлено, между клиентом и сервером осуществляется следующая последовательность действий.
Клиент отправляет серверу четыре строки: (a) нулевой байт, (b) имя пользователя на хосте клиента, заканчивающееся нулевым байтом, (с) имя пользователя на хосте сервера, заканчивающееся нулевым байтом, (d) тип терминала пользователя, за которым следует слэш (/), затем следует скорость терминала, и все это заканчивается нулевым байтом. Необходимо отправить именно два имени пользователя, потому что пользователи не обязаны иметь одинаковые имена на разных хостах.
Тип терминала передается от клиента к серверу, потому что эта информация необходима для большинства полноэкранных приложений. Скорость терминала передается, потому что некоторые приложения работают по-разному в зависимости от скорости. Например, редактор vi работает с меньшими окнами, когда работает с меньшими скоростями, при этом он не должен постоянно перерисовывать окно.
Сервер отвечает нулевым байтом. У сервера есть опция, с помощью которой он просит ввести пароль. Это осуществляется как обычный обмен данными по Rlogin соединению - специальные протоколы не применяются. Сервер отправляет клиенту строку (которую клиент отображает на терминале), чаще всего эта строка выглядит как Password:. Если клиент не вводит пароль в течение определенного времени (обычно 60 секунд), сервер закрывает соединение. В домашней директории на сервере можно создать файл (который называется .rhosts) в котором будут содержаться имя хоста и имя пользователя. Если зайти терминалом с указанного хоста с указанным именем пользователя, то не выдается приглашение ввести пароль. В некоторых публикациях, посвященных безопасности компьютерных систем, как, например, [Curry 1992], очень не рекомендуют пользоваться этой характеристикой, потому что в этом случае в секретности появляется порядочная брешь. Все что вводится в ответ на приглашение сервера ввести пароль, передается в виде открытого текста. Символы введенного пароля посылаются так, как они есть. Каждый, кто может прочитать пакеты в сети, может прочитать любой пароль. Последние реализации Rlogin клиента, например в 4.4BSD, используют Kerberos для шифрации при передаче по сети. Естественно требуются, чтобы и сервер поддерживал Kerberos. ([Curry 1992] описывает Kerberos более подробно.) Сервер обычно отправляет запрос клиенту, спрашивая размер окна терминала (это будет описано позже).Клиент посылает за один раз серверу 1 байт, каждый байт сервер отражает эхо-откликом. Мы это видели в разделе "Интерактивный ввод" главы 19. Обычно используется алгоритм Нагла (глава 19, раздел "Алгоритм Нагла"), поэтому несколько входных байтов отправляются по медленным сетям как один TCP сегмент. Функционально все довольно просто: то, что вводит пользователь, отправляется на сервер, а то, что сервер отправляет клиенту, отображается на терминале.
Существуют команды, которые могут быть отправлены от клиента к серверу и от сервера к клиенту. Давайте, во-первых, опишем сценарий, по которому работают эти команды.
Номер сегмента
(рисунок 21.7) |
Действие | Переменная | |||
Отправлено | Получено | Комментарий | cwnd | ssthresh | |
58 | ACK 6657 | подтверждение новых данных | 2426 | 512 | |
59 | 8705:8961(256) | ||||
60 | ACK 6657 | дублированный ACK номер 1 | 2426 | 512 | |
61 | ACK 6657 | дублированный ACK номер 2 | 2426 | 512 | |
62 | ACK 6657 | дублированный ACK номер 3 | 1792 | 1024 | |
63 | 6657:6913(256) | повторная передача | |||
64 | ACK 6657 | дублированный ACK номер 4 | 2048 | 1024 | |
65 | ACK 6657 | дублированный ACK номер 5 | 2304 | 1024 | |
66 | ACK 6657 | дублированный ACK номер 6 | 2560 | 1024 | |
67 | 8961:9217(256) | ||||
68 | ACK 6657 | дублированный ACK номер 7 | 2816 | 1024 | |
69 | 9217:9473(256) | ||||
70 | ACK 6657 | дублированный ACK номер 8 | 3072 | 1024 | |
71 | 9473:9729(256) | ||||
72 | ACK 8961 | подтверждение новых данных | 1280 | 1024 |
Третья цифра дает дополнительное объяснение сообщению об ошибке. Ниже приведены некоторые типичные отклики с возможными объясняющими строками. 125 Соединение данных уже открыто; начало передачи. 200 Команда исполнена. 214 Сообщение о помощи (для пользователя). 331 Имя пользователя принято, требуется пароль. 425 Невозможно открыть соединение данных. 452 Ошибка записи файла. 500 Синтаксическая ошибка (неизвестная команда). 501 Синтаксическая ошибка (неверные аргументы). 502 Нереализованный тип MODE.
Обычно каждая FTP команда генерируют отклик в одну строку. Например, команда QUIT сгенерирует следующий отклик:
221 Goodbye.
Если необходим отклик в несколько строк, первая строка содержит дефис вместо пробела после 3-циферного кода отклика, а последняя строка содержит тот же самый 3-циферный код отклика, за которым следует пробел. Например, команда HELP сгенерирует следующий отклик:
214- The following commands are recognized (* =>'s unimplemented).
USER PORT STOR MSAM* RNTO NLST MKD CDUP
PASS PASV APPE MRSQ* ABOR SITE XMKD XCUP
ACCT* TYPE MLFL* MRCP* DELE SYST RMD STOU
SMNT* STRU MAIL* ALLO CWD STAT XRMD SIZE
REIN* MODE MSND* REST XCWD HELP PWD MDTM
QUIT RETR MSOM* RNFR LIST NOOP XPWD
214 Direct comments to ftp-bugs@bsdi.tuc.noao.edu.
Управление соединением
Использовать соединение данных можно тремя способами. Отправка файлов от клиента к серверу. Отправка файлов от сервера к клиенту. Отправка списка файлов или директорий от сервера к клиенту.
FTP сервер посылает список файлов по соединению данных, вместо того чтобы посылать многострочные отклики по управляющему соединению. При этом появляется возможность избежать любых ограничений в строках, накладывающихся на размер списка директории, и позволяет просто сохранить список директории в файле, вместо того чтобы выдавать список на терминал.
Мы сказали, что управляющее соединение остается в активизированном состоянии все время, пока установлено соединение клиент-сервер, однако соединение данных может выключаться и включаться по необходимости. Как выбираются номера портов для соединения данных, и кто осуществляет активное открытие, а кто пассивное открытие?
Во-первых, как было сказано ранее, распространенный режим передачи (в случае Unix это единственный режим передачи) - это потоковый режим. В этом режиме конец файла обозначает закрытие соединения данных. Из этого следует, что для передачи каждого файла или списка директории требуется новое соединение данных. Обычная процедура выглядит следующим образом:
Создание соединения данных осуществляется клиентом, потому что именно клиент выдает команды, которые требуют передать данные (получить файл, передать файл или список директории). Клиент обычно выбирает динамически назначаемый номер порта на хосте клиента для своего конца соединения данных. Клиент осуществляет пассивное открытие с этого порта. Клиент посылает этот номер порта на сервер по управляющему соединению с использованием команды PORT. Сервер принимает номер порта с управляющего соединения и осуществляет активное открытие на этот порт хоста клиента. Сервер всегда использует порт 20 для соединения данных.
На рисунке 27.4 показано состояние соединений, пока осуществляется шаг номер 3. Мы предполагаем, что динамически назначаемый порт клиента для управляющего соединения имеет номер 1173, а динамически назначаемый порт клиента для соединения данных имеет номер 1174. Команда, посылаемая клиентом - PORT, а ее аргументы это шесть десятичных цифр в формате ASCII, разделенные запятыми. Четыре первых числа - это IP адрес клиента, на который сервер должен осуществить активное открытие (140.252.13.34 в данном примере), а следующие два - это 16-битный номер порта. Так как 16-битный номер порта формируется из двух цифр, его значение в этом примере будет 4 x 256 + 150 = 1174.
На рисунке 27.5 показано состояние соединений, когда сервер осуществляет активное открытие на конец клиента соединения данных. Конечная точка сервера это порт 20.
Если возникла ошибка, индекс ошибки (error index) это целое смещение, указывающее на то, в какой переменной произошла ошибка. Это значение устанавливается агентом только для ошибок noSuchName (нет такого имени), badValue (неверное значение) и readOnly (только для чтения).
Список имен переменных и значений следует в get, get-next и set запросах. Раздел значений игнорируется в операторах get и get-next.
Для оператора trap (PDU type равен 4) формат SNMP сообщения изменяется. Мы опишем поля заголовка ловушки, когда будем описывать этот оператор в разделе "Ловушки" этой главы.