Тайм-ауты и повторные передачи TCP

         

Изменения размера окна



Изменения размера окна

Если существует возможность поделить дисплей на окна, мы можем динамически менять размер окна, в процессе работы приложения. Некоторые приложения (обычно те, которые манипулируют с целыми окнами, такие как полноэкранные редакторы) должны знать об этих изменениях. Большинство Unix систем каким-либо образом сообщают приложению об изменении размера окна.

В случае захода удаленным терминалом, изменения размера окна происходят на компьютере клиента, и об этом необходимо сообщить приложению, которое работает на сервере. Клиенту Rlogin необходима некоторая форма уведомления, для того чтобы сообщить серверу об изменении размера окна и о том, чему теперь равен новый размер окна.



Изменения в конверте расширенное SMTP



Изменения в конверте: расширенное SMTP

RFC 1425 [Klensin et al. 1993a] определяет основные расширения для SMTP. В результате получилось то, что называется расширенным SMTP (ESMTP - extended SMTP). Как и другие новые характеристики (уже описанные в тексте), эти изменения добавляются таким образом, что новые версии совместимы со старыми.

Клиент, которому необходимо использовать новые характеристики, открывает сессию с сервером с использованием команды EHLO вместо команды HELO. Совместимый сервер отвечает откликом с кодом 250. Этот отклик обычно содержит несколько строк, причем каждая строка содержит ключевое слово и дополнительный аргумент. Ключевые слова указывают на расширения SMTP, поддерживаемые сервером. (В случае многострочного отклика во всех строках кроме последней, между цифровым кодом и текстом стоит дефис. В последней строке между цифровым кодом и текстом стоит пробел.) Вновь появляющиеся расширения будут описаны в RFC и будут зарегистрированы в IANA.

Ниже показаны начальные стадии соединений с четырьмя SMTP серверами, три из которых поддерживают расширенный SMTP. Соединение осуществляется с помощью Telnet, однако весь вывод Telnet клиента удален.

sun % telnet vangogh.cs.berkeley.edu 25
220-vangogh.CS.Berkeley.EDU Sendmail 8.1C/6.32 ready at Mon, 2 Aug 1993 15:47:48 -0700
220 ESMTP spoken here

ehlo sun.tuc.noao.edu
250-vangogh.CS.Berkeley.EDU Hello sun.tuc.noao.edu [140.252.1.29], pleased to meet you
250-EXPN
250-SIZE
250 HELP

Этот сервер выдает многострочный отклик 220 в виде приветственного сообщения. Расширенные команды, приведенные в отклике 250, на команду EHLO это EXPN, SIZE и HELP. Первая и последняя из исходной спецификации RFC 821, однако они являются дополнительными командами (необязательными). Сервера ESMTP помимо дополнительных команд из RFC 821 поддерживают также и более новые команды.

Ключевое слово SIZE означает, что сервер поддерживает то, что описано в RFC 1427 [Klensin, Freed, and Moore 1993]. Подобное расширение позволяет клиенту указывать размер сообщения в байтах в командной строке MAIL FROM. Это позволяет серверу проверить, что он воспримет сообщение определенного размера, перед тем как клиент начнет его посылать. Эта команда была добавлена, так как в последнее время появляется все больше почтовых сообщений содержащих не-ASCII строки (например, бинарные или звуковые файлы).

Следующий хост также поддерживает ESMTP. Отклик 250 указывает, что поддерживаемое ключевое слово SIZE содержит дополнительный аргумент. Он указывает на то, что этот сервер может воспринимать сообщения размером до 461 мегабайта.

sun % telnet ymir.claremont.edu 25
220 ymir.claremont.edu -- Server SMTP (PMDF V4.2-13 #4220)

ehlo sun.tuc.noao.edu
250-ymir.claremont.edu
250-8BITMIME
250-EXPN
250-HELP
250-XADR
250 SIZE 461544960

Ключевое слово 8BITMIME определено в RFC 1426 [Klensin et al. 1993b]. Оно позволяет клиенту добавить ключевое слово BODY к команде MAIL FROM, указывая тем самым, содержит ли тело сообщения NVT ASCII символы (по умолчанию) или 8-битные данные. Если клиент не получил ключевое слово 8BITMIME от сервера в ответ на команду EHLO, клиенту запрещено посылать любые другие символы кроме NVT ASCII. (Когда мы будем говорить о MIME в этом разделе, то увидим, что для MIME не требуется 8-битный SMTP транспорт.)

Этот сервер также объявил ключевое слово XADR. Любое ключевое слово, которое начинается на X, обозначает местное расширение SMTP.

Следующий сервер также поддерживает ESMTP, объявляя ключевые слова HELP и SIZE, которые мы уже видели. Он также поддерживает три локальных расширения, которые начинаются на X.

sun % telnet dbc.mtview.ca.us 25
220 dbc.mtview.ca.us Sendmail 5.65/3.1.090690, it's Mon, 2 Aug 93 15:48:50 -0700

ehlo sun.tuc.noao.edu
250-Hello sun.tuc.noao.edu, pleased to meet you
250-HELP
250-SIZE
250-XONE
250-XVRB
250 XQUE

И в конце мы посмотрим, что произойдет, когда клиент пытается использовать ESMTP, выдав команду EHLO на сервер, который это не поддерживает.

sun % telnet relay1.uu.net 25
220 relay1.UU.NET Sendmail 5.61/UUNET-internet-primary ready at Mon, 2 Aug 93 18:50:27 -0400

ehlo sun.tuc.noao.edu
500 Command unrecognized

rset
250 Reset state



Вместо того чтобы получить отклик 250 на команду EHLO, клиент получил отклик 500. Затем клиент должен исполнить команду RSET, а уже затем команду HELO.



Изменения в теле сообщения Многофункциональные



Изменения в теле сообщения: Многофункциональные расширения почты Internet (MIME - Multipurpose Internet Mail Extensions)

Мы говорили, что RFC 822 описывает тело сообщения как строки NVT ASCII текста, без структуры. RFC 1521 [Borenstein and Freed 1993] определяет расширения, которые позволяют вводить структуру в тело сообщения. Это называется многофункциональным расширением почты Internet (MIME - Multipurpose Internet Mail Extensions).

MIME не требует тех расширений, что мы описали ранее в этом разделе (расширенный SMTP или не-ASCII заголовки). MIME просто добавляет некоторые новые заголовки (в соответствии с RFC 822), которые сообщают получателю о структуре тела сообщения. Тело сообщения может передаваться с использованием NVT ASCII, вне зависимости от содержимого почты. Несмотря на это некоторые из расширений, которые мы только что описали, могут быть вполне уместны при использовании вместе с MIME - команда SIZE расширенного SMTP, так как MIME сообщения могут быть довольно большими, и не-ASCII заголовки, эти расширения не требуются для MIME. Все что требуется для обмена MIME сообщениями с другой стороной - необходимо, чтобы на обоих концах присутствовали пользовательские агенты, которые понимают MIME. На промежуточных MTA не требуется никаких изменений.

MIME определяет пять новых полей заголовков:

Mime-Version:
Content-Type:
Content-Transfer-Encoding:
Content-ID:
Content-Description:

В качестве примера, приведены две строки заголовка, которые могут присутствовать в почтовом сообщении Internet:

Mime-Version: 1.0
Content-Type: TEXT/PLAIN; charset=US-ASCII

Текущая версия MIME - 1.0, в которой сообщения выглядят как простой ASCII текст, что является форматом по умолчанию для почты Internet. Слово PLAIN определяет подтип типа содержимого (TEXT), а строка charset=US-ASCII это параметр.

Text это всего лишь один из семи определенных в MIME типов содержимого. На рисунке 28.7 приводится краткое описание 16 различных типов содержимого и подтипов, определенных в RFC 1521. Для конкретных типов содержимого и подтипов может быть определено большое количество параметров.

Тип содержимого и кодирование при передаче, применяемое к телу сообщения, независимы друг от друга. Здесь указаны поле заголовка Content-Type (тип содержимого) и поле заголовка Content-Transfer-Encoding (кодирование содержимого при передаче). В RFC 1521 определено пять различных форматов кодирования. 7bit, что является NVT ASCII, по умолчанию. quoted-printable, как мы видели в примере, приведенном ранее, используется с не-ASCII заголовками. Подобный тип кодирования применим, только когда небольшое количество символов имеет установленный восьмой бит. base64, показан на рисунке 28.6. 8bit содержит строки символов, некоторые из которых не-ASCII и имеют установленный восьмой бит. binary кодирование, используется в случае 8-битных данных, которые не содержат строк.

Тип содержимого Подтип Описание
text plain Неформатированный текст.
richtext Текст с простым форматированием, как, например, выделение жирным шрифтом, курсивом, подчеркивание и так далее.
enriched Прояснение, упрощение и усовершенствование richtext.
multipart mixed Несколько частей тела сообщения обрабатываются последовательно.
parallel Несколько частей тела сообщения могут быть обработаны параллельно.
digest Краткое изложение почты.
alternative Присутствует несколько частей тела сообщения, все с идентичным семантическим содержанием.
message rfc822 Содержимое это еще одно почтовое сообщение RFC 822.
partial Содержимое это фрагмент почтового сообщения.
external-body Содержимое это указатель на реальное сообщение.
application octet-stream Произвольные двоичные данные.
postscript Программа PostScript.
image jpeg Формат ISO 10918.
gif Формат CompuServe's Graphic Interchange.
audio basic Кодирование с использованием 8-битного ISDN формата m -law.
video mpeg Формат ISO 11172.


Изменения в заголовках использование неASCII символов



Изменения в заголовках: использование не-ASCII символов

RFC 1522 [Moore 1993] указывает способы передачи не-ASCII символов в заголовках сообщений, основанных на RFC 822. Основное назначение - разрешить использовать дополнительные символы в именах отправителя и получателя, а также в теме сообщения.

Поле заголовка может содержать закодированные слова. При этом формат следующий:

=? charset ? encoding ? encoded text ?=

charset это спецификация набора символов. Приемлемые значения это две строки us-ascii и iso-8859-X, где X это одна цифра, как, например, iso-8859-1.

encoding это один символ, который указывает метод кодирования. Поддерживаются два значения.

Q означает quoted-printable и предназначен для латинского набора символов. Большинство символов передаются как NVT ASCII (старший бит установлен в 0, естественно). Любой отправляемый символ, у которого восьмой бит не равен 0, посылается как три символа: первый символ =, после чего следуют две шестнадцатиричные цифры. Например, символ й (бинарное 8-битное значение которого равно 0xe9) передается как три символа =E9. Пробелы всегда отправляются либо как подчеркивание, либо как три символа =20. Такое кодирование используется для текста, который в основном состоит из ASCII с небольшим количеством специальных символов. B означает кодирование по основанию 64. Три последовательных байта текста (24 бита) кодируются как четыре 6-битных значения. Для того, чтобы представить каждое из возможных 6-битных значений, используется, 64 символа NVT ASCII, как показано на рисунке 28.6.

6-битное значение ASCII символ 6-битное значение ASCII символ 6-битное значение ASCII символ 6-битное значение ASCII символ
0 A 10 Q 20 g 30 w
1 B 11 R 21 h 31 x
2 C 12 S 22 i 32 y
3 D 13 T 23 j 33 z
4 E 14 U 24 k 34 0
5 F 15 V 25 l 35 1
6 G 16 W 26 m 36 2
7 H 17 X 27 n 37 3
8 I 18 Y 28 o 38 4
9 J 19 Z 29 p 39 5
a K 1a a 2a q 3a 6
b L 1b b 2b r 3b 7
c M 1c c 2c s 3c 8
d N 1d d 2d t 3d 9
E O 1e e 2e u 3e +
f P 1f f 2f v 3f /


Электронная почта по Internet с транслирующими системами на обоих концах



Рисунок 28.3 Электронная почта по Internet с транслирующими системами на обоих концах.


В разделе "Будущее SMTP" этой главы мы обсудим некоторые более новые характеристики почты в Internet, расширенный SMTP и мультимедийную почту (MIME), которая позволяет отправлять и принимать звуковую и видео информацию. Мы увидим, что MIME использует NVT ASCII в качестве конверта, заголовка и тела, а изменения касаются только пользовательских агентов.



Это временная диаграмма для соединения



Рисунок 27.7 это временная диаграмма для соединения данных. Времена на этом рисунке начинаются с того же момента, как и на рисунке 27.6. Мы удалили все объявления окна, однако оставили поле типа сервиса, чтобы показать, что соединение данных использует отличный тип сервиса (максимальная пропускная способность), нежели управляющее соединение (минимальная задержка). (Значения TOS приведены на рисунке 3.2.)

На этой временной диаграмме FTP сервер осуществляет активное открытие соединения данных с порта 20 (который называется ftp-data) на номер порта из команды PORT (1174). Также в этом примере, где сервер выдает информацию в соединение данных, сервер осуществляет активное закрытие соединения данных, тем самым сообщая клиенту, когда список завершен.



Как получатель избавляется от синдрома глупого окна



Рисунок 22.3 Как получатель избавляется от синдрома глупого окна.

В первой колонке на рисунке 22.3 приводится относительный момент времени соответствующий каждому действию. Величины времени с тремя цифрами справа от десятичной точки взяты из вывода команды tcpdump (рисунок 22.2). Величины времени со значением 99 справа от десятичной точки - это предполагаемая продолжительность функционирования принимающего хоста. (Наличие этих относительных времен на принимающем конце и содержащих 99 в позиции сотых долей секунд указывает на их взаимосвязь с сегментами 20 и 22 на рисунке 22.2, только два события на приемнике, которые мы видим в выводе команды tcpdump, произошли на принимающем хосте по тайм-ауту. Все другие пакеты, отправленные bsdi, отправлены по приему сегмента от отправителя. Также необходимо принять во внимание, что это могло бы поместить исходную 4-секундную паузу непосредственно перед моментом времени 0, когда отправитель передает первый сегмент данных. Это примерно тогда, когда получатель берет управление после приема подтверждения на свой SYN при установлении соединения.)

Размер буфера приемника увеличивается, когда он получает данные от получателя, и уменьшается, когда приложение считывает данные из буфера. Нам необходимо проследить за объявлениями окна, которые отправляются получателем отправителю, и за тем, что содержат эти объявления окна. Таким образом, мы можем увидеть, как получатель избегает синдрома глупого окна.

Первые четыре сегмента данных и соответствующие ACK (сегменты 1-5) показывают, что отправитель заполнил буфер приемника. В этой точке отправитель останавливается, однако у него все еще остались данные, которые необходимо отправить. Он устанавливает свой устойчивый таймер в минимальное значение равное 5 секундам.

Когда таймер истек, посылается 1 байт данных (сегмент 6). Принимающее приложение считало 256 байт из приемного буфера (в момент времени 3,99), таким образом, байт принимается и подтверждается (сегмент 7). Однако, объявленное окно все еще равно 0, так как у приемника нет места равного одному сегменту полного размера или половине своего буфера. Именно таким образом, получатель избегает появления синдрома глупого окна.

Устойчивый таймер отправителя сбрасывается и устанавливается снова через 5 секунд (момент времени 10,151). Снова отправляется и подтверждается один байт (сегменты 8 и 9). И снова, размер свободного места в буфере приемника (1022 байта) заставляет его объявить окно равное 0.

Когда устойчивый таймер отправителя истекает в следующий раз (в момент времени 15,151), отправляется и подтверждается еще один байт (сегменты 10 и 11). В это время получатель имеет в буфере 1533 байта свободного пространства, поэтому объявляется окно ненулевого размера. Отправитель немедленно пользуется этим и отправляет 1024 байта (сегмент 12). Подтверждение на эти 1024 байта (сегмент 13) объявляет окно равное 509 байт. Это противоречит тому, что мы видели раньше с объявлениями маленьких окон.

Здесь произошло следующее: сегмент 11 объявил окно размером 1533 байта, однако отправитель отправил только 1024 байта. Если подтверждение в сегменте 13 объявит окно равное 0, это будет противоречить принципу TCP, который заключается в том, что окно не может изменяться путем перемещения его правого края влево (глава 20, раздел "Изменение размера окна"). Именно поэтому должно быть объявлено маленькое окно размером в 509 байт.

Затем необходимо обратить внимание на то, что отправитель отправляет это маленькое окно не сразу. Это уже меры, которые принимает отправитель, чтобы избавиться от синдрома глупого окна. Отправитель ожидает истечения еще одного устойчивого таймера (момент времени 20,151) и только тогда посылает 509 байт. Даже если все равно отправляется маленький сегмент размером 509 байт данных, отправитель ожидает 5 секунд, чтобы посмотреть, не придет ли ACK и не объявит ли большее окно. После прихода 509 байт данных в буфере приемника остается всего лишь 768 байт свободного места, поэтому подтверждение (сегмент 15) объявляет окно равное 0.

Устойчивый таймер снова включается в момент времени 25,151, а отправитель передает 1 байт. В буфере получателя этот момент 1279 байт свободного пространства, окно такого размера объявляется в сегменте 17.

Отправителю необходимо отправить только 511 дополнительных байт, которые он немедленно отправляет после получения объявления окна размером 1279 байт (сегмент 18). Этот сегмент также содержит флаг FIN. Получатель подтверждает данные и FIN, объявляя окно размером 767. (См. упражнение 2 в конце главы.)

Так как отправляющее приложение выдало сигнал закрытия, после того как сделало шесть записей размером 1024 байта, соединение со стороны отправителя переходит из состояния ESTABLISHED в состояние FIN_WAIT_1, затем в состояние FIN_WAIT_2 (рисунок 18.12).

Оно остается в этом состоянии до получения FIN с удаленного конца. Для этого состояния не существует таймера (обратитесь к нашему обсуждению в конце раздела "Диаграмма состояний передачи TCP" главы 18), поэтому FIN, который был отправлен в сегменте 18, подтверждается в сегменте 19. Именно поэтому мы не видим дальнейшей передачи от отправителя до тех пор, пока он не получил FIN (сегмент 21).

Получающее приложение продолжает читать 256 байт данных каждые 2 секунды из приемного буфера. Почему ACK отправлен в момент времени 39,99 (сегмент 20)? Размер свободного места в буфере получателя увеличился с момента последнего объявления окна размером 767 (сегмент 19) до 2816, когда приложение осуществило чтение в момент времени 39,99. Таким образом, в приемном буфере появилось 2049 байт свободного пространства. Обратитесь к первому правилу, с которого мы начали этот раздел, в соответствии с которым получатель отправляет обновление окна, потому что количество свободного места увеличилось на величину, равную половине размера приемного буфера. Это означает, что получающий TCP каждый раз проверяет, нужно ли послать обновления окна, когда приложение считывает данные из приемного буфера TCP.

Последнее чтение, осуществленное приложением, происходит в момент времени 51,99, и приложение получает уведомление о конце файла, так как буфер пуст. Два последних сегмента (21 и 22) завершают разрыв соединения.



Каналы с повышенной пропускной способностью (Long Fat Pipes)



Каналы с повышенной пропускной способностью (Long Fat Pipes)

В разделе "Пропускная способность для неинтерактивных данных" главы 20 мы сказали, что емкость соединения можно рассчитать следующим образом

емкость (бит) = ширина полосы (бит/сек) x время возврата (сек)

и назвали это емкость канала в зависимости от полосы пропускания. Иногда эта величина называется размером канала между двумя точками.

Существующие ограничения TCP начинают влиять на производительность по мере увеличения емкости каналов. На рисунке 24.5 показаны некоторые значения для различных типов сетей.

Сеть Ширина полосы (бит/сек) Время возврата (миллисекунды) Емкость канала (байты)
Локальная сеть на основе Ethernet 10000000 3 3750
Трансконтинентальный канал, телефонная линия T1 1544000 60 11580
Спутниковый канал, телефонная линия T1 1544000 500 95500
Трансконтинентальный канал, телефонная линия T3 45000000 60 337500
Трансконтинентальный гигабитный канал 1000000000 60 7500000


Кнопка прерывания клиента



Кнопка прерывания клиента

Давайте рассмотрим еще один пример, в котором TCP использует режим срочности, когда поток данных остановлен с помощью символа прерывания. В этом примере сведены вместе несколько алгоритмов TCP, которые мы обсуждали ранее: режим срочности, предотвращение "глупого" окна, управление потоком данных с помощью окон и устойчивого таймера. Мы стартовали клиента на хосте sun. Затем зашли терминалом на bsdi, вывели на терминал большой текстовый файл, а затем остановили вывод, нажав Control-S. Когда вывод остановлен, мы нажали клавишу прерывания (DELETE), чтобы завершить работу программы:


sun % rlogin bsdi
приветствие от операционной системы
bsdi % cat /usr/share/misc/termcap вывод большого файла на терминал
большой вывод на терминал
мы печатаем Control-S, чтобы остановить вывод,
и ожидаем до тех пор, пока вывод не остановится

^? вводим символ прерывания, он отображается эхом
bsdi % затем появляется приглашение

Ниже описаны состояния клиента, сервера и соединения.

Вывод на терминал остановлен путем ввода Control-S. Rlogin клиент приостановил вывод на терминал, однако выходной буфер терминала будет заполнен. Rlogin клиент не может читать из сети, так как приемный буфер TCP клиента полон. TCP клиент объявляет размер окна равный 0, чтобы остановить отправителя (TCP модуль Rlogin сервера), когда приемный буфер полон. TCP модуль сервера отправляет сообщение о заполнении буфера, когда его вывод остановлен сообщением от клиента о том, что размер окна равен 0. Сервер Rlogin остановлен, так как отправляющий буфер полон. Таким образом, сервер Rlogin не может читать данные от приложения, которое запущено на сервере (cat). Приложение cat останавливается, когда его выходной буфер наполняется. Затем мы вводим символ прерывания, чтобы остановить работу приложения cat на сервере. Это отправляется от TCP клиента к TCP серверу, потому что поток данных в этом направлении не остановлен с помощью контроля потока данных. Приложение cat получает символ прерывания и прекращает свою работу. При этом его выходной буфер (из которого читал сервер Rlogin) очищается, после чего "просыпается" сервер Rlogin. Сервер Rlogin входит в режим срочности и посылает клиенту команду "очистить вывод" (0x02).

На рисунке 26.6 показан поток данных от сервера к клиенту. (Номера последовательности взяты из временной диаграммы, которую мы покажем чуть ниже.)



Кодирование 6битных значений (кодирование на основе 64)



Рисунок 28.6 Кодирование 6-битных значений (кодирование на основе 64).

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

Следующий пример этих двух типов кодирования взят из RFC 1522:

From: =?US-ASCII?Q?Keith_Moore?= <moore@cs.utk.edu>
To: =?ISO-8859-1?Q?Keld_J=F8rn_Simonsen?= <keld@dkuug.dk>
CC: =?ISO-8859-1?Q?Andr=E9_?= Pirard <PIRARD@vm1.ulg.ac.be>
Subject: =?ISO-8859-1?B?SWYgeW91IGNhbiByZWFkIHRoaXMgeW8=?=
=?ISO-8859-2?B?dSB1bmRlcnN0YW5kIHRoZSBleGFtcGxlLg==?=

Пользовательский агент имеет возможность обработать эти заголовки, в результате чего получится следующий вывод:

From: Keith Moore <moore@cs.utk.edu>
To: Keld Jorn Simonsen <keld@dkuug.dk>
CC: Andre Pirard <PIRARD@vm1.ulg.ac.be>
Subject: If you can read this you understand the example.

Для того чтобы посмотреть, как работает кодирование на основе 64, посмотрите на первые 4 закодированных символа в строке темы: SWYg. Напишем 6-битные значения для этих 4 символов в соответствии с рисунком 28.6 (S=0x12, W=0x16, Y=0x18 и g=0x20) в двоичном виде:

010010 010110 011000 100000

Затем перегруппируем эти 24 бита в три 8-битных байта:


01001001 01100110 00100000
=0x49 =0x66 =0x20

которые в виде ASCII представляют собой I, f и пробел.



Коды опций Telnet обсуждаемые в этой главе



Рисунок 26.10 Коды опций Telnet, обсуждаемые в этой главе.

Обсуждение опции Telnet, как и многое другое в протоколе Telnet, процесс симметричный. Каждая сторона может начать процесс обсуждения опции. Однако заход удаленным терминалом не является симметричным процессом. Клиент решает свои задачи, а сервер свои. Мы увидим, что некоторые опции Telnet применимы только к клиенту (например, требование включить линейный режим (linemode)), а некоторые предназначены только для сервера.



Команда PORT передаваемая по управляющему соединению FTP



Рисунок 27.4 Команда PORT, передаваемая по управляющему соединению FTP.












Команды FTP



Команды FTP

Команды и отклики передаются по управляющему соединению между клиентом и сервером в формате NVT ASCII. В конце каждой строки команды или отклика присутствует пара CR, LF.

Единственные команды Telnet (начинающиеся с IAC), которые могут быть отправлены клиентом серверу - это команда прерывания процесса (<IAC, IP>) и Telnet сигнал синхронизации (<IAC, DM> в режиме срочности). Мы увидим, что эти две команды Telnet используются для прекращения передачи файла или для того, чтобы отправить серверу запрос в процессе передачи. Если сервер получает от клиента команду с Telnet опцией (WILL, WONT, DO или DONT), он отвечает либо DONT, либо WONT.

Команды состоят из 3 или 4 байт, а именно из заглавных ASCII символов, некоторые с необязательными аргументами. Клиент может отправить серверу более чем 30 различных FTP команд. На рисунке 27.2 показаны некоторые наиболее широко используемые команды, большинство из которых мы рассмотрим в этой главе.

Команда Описание
ABOR прервать предыдущую команду FTP и любую передачу данных
LIST список файлов список файлов или директорий
PASS пароль пароль на сервере
PORT n1,n2,n3,n4,n5,n6 IP адрес клиента (n1.n2.n3.n4) и порт (n5 x 256 + n6)
QUIT закрыть бюджет на сервере
RETR имя файла получить (get) файл
STOR имя файла положить (put) файл
SYST сервер возвращает тип системы
TYPE тип указать тип файла: A для ASCII, I для двоичного
USER имя пользователя имя пользователя на сервере


Команды от клиента к серверу



Команды от клиента к серверу

В настоящее время определена только одна команда, передаваемая от клиента к серверу: это отправка серверу текущего размера окна. Изменение размера окна не отправляется серверу пока клиент не получит от сервера команду 0x80 (рисунок 26.4).

И снова, так как используется одно TCP соединение, клиент должен иметь возможность пометить свои команды, чтобы они не были переданы приложению, запущенному на сервере. Клиент помечает команды с помощью отправки 2-х байт равных 0xff, за которыми следуют два специальных флаговых байта.

Для команды, управляющей размером окна, два флаговых байта это ASCII символы s. Затем следуют четыре 16-битных значения (в порядке сетевых байтов): количество символов в строке (обычно 25), количество символов в столбце (обычно 80), количество пикселей по оси X и количество пикселей по оси Y. Часто два последних 16-битных значения равны 0, так как большинство приложений, запускаемых Rlogin сервером, определяют размер экрана в символах, а не в пикселях.

Подобная форма представления команд называется командами в полосе (in-band signaling), так как командные байты передаются в обычном потоке данных. Байты, выделяющие команды из потока данных (0xff) выбраны таким образом, нажатие какой-либо клавиши не могло сгенерировать подобные байты. Естественно у подобной формы представления команд есть свои недостатки. Если мы сможем сгенерировать два последовательных байта равных 0xff с клавиатуры, за которыми будут следовать два ASCII символа s, следующие 8 введенных байт будут восприняты как размеры окна.

Команды Rlogin от сервера к клиенту, показанные на рисунке 26.4, называются командами, выходящими за полосу (out-of-band signaling), именно так эта техника называется в большинстве API. Обратитесь к режиму срочности TCP (глава 20, раздел "Режим срочности (Urgent Mode)"). Режим срочности не имеет отношения к данным, выходящим за полосу, так как командные байты передаются в обычном потоке данных, при этом их местоположение в потоке данных определяется с использованием указателя срочности.

Так как команды в полосе (in-band signaling) передаются от клиента к серверу, сервер должен просматривать каждый байт, принятый от клиента, в поисках двух последовательных байтов 0xff. В случае команд выходящих за полосу (out-of-band signaling) , которые передаются от сервера к клиенту, клиенту нет необходимости просматривать данные, которые он получает от сервера, до тех пор пока сервер не перейдет в режим срочности. Даже в режиме срочности клиенту необходимо только просмотреть байт, на который указывает указатель срочности. Так как соотношение количества байт, передаваемых в двух направлениях (от клиента к серверу и от сервера к клиенту), составляет примерно 1:20, то возникает необходимость использовать команды в полосе (in-band signaling) для небольшого потока данных (от клиента к серверу), и команды, выходящие за полосу (out-of-band signaling), для более загруженного потока данных (от сервера к клиенту).



Команды от сервера к клиенту



Команды от сервера к клиенту

Давайте кратко рассмотрим четыре команды, которые сервер Rlogin может отправить клиенту по TCP соединению. Проблема заключается в том, что используется одно TCP соединение, поэтому сервер должен пометить байты команд так, чтобы клиент интерпретировал их именно как команды, а не отображал эти байты на терминале. Для этого используется режим срочности TCP (глава 20, раздел "Режим срочности (Urgent Mode)").

Когда сервер отправляет команду клиенту, он входит в режим срочности, при этом последний байт срочных данных это и есть байт команды от сервера. Когда клиент получает уведомление о режиме срочности, он читает из соединения и сохраняет данные до тех пор, пока не будет получен байт с командой (последний байт срочных данных). Данные, которые сохранил клиент, могут быть выданы на терминал или проигнорированы, в зависимости от команды. На рисунке 26.4 описываются четыре командных байта.

Байт Описание
0х02 Сбросить вывод. Клиент отбрасывает все данные, принятые от сервера, до командного байта (последний байт срочных данных). Клиент также отбрасывает все данные, сбуферизированные и предназначенные для вывода на терминал. Сервер посылает эту команду, когда пользователь ввел символ прерывания.
0х10 Клиент прекращает контролировать поток данных.
0х20 Клиент возобновляет контроль потока данных.
0х80 Клиент немедленно отвечает отправкой серверу текущего размера окна и уведомляет сервер, если в будущем размер окна изменится. Сервер обычно отправляет эта команду немедленно после установления соединения.


Команды Rlogin передаваемые от сервера клиенту



Рисунок 26.4 Команды Rlogin, передаваемые от сервера клиенту.

Одна из причин, по которой описанные выше команды посылаются с использованием режима срочности TCP, заключается в том, что первая команда (flush output) должна быть отправлена клиенту, даже если поток данных от сервера к клиенту остановлен контролем потока данных TCP. Ситуация когда передача информации от сервера к клиенту остановлена управлением потоком данных может возникнуть, так как процессы, запущенные на сервере, обычно генерируют вывод быстрее, чем этот он может быть отображен на терминале клиента. Однако, достаточно редко может возникнуть ситуация, когда передача информациии от клиента к серверу будет остановлена управлением потоком данных, так как в этом направлении поток данных содержит только символы, вводимые пользователем.

Обратитесь к рисунку 20.14, где показано, что уведомление о срочности проходит по соединению, даже если размер окна был установлен в 0. (Мы увидим еще один пример этого в следующем разделе.) Оставшиеся три команды не критичны по времени, однако они используют ту же технику для упрощения реализации.



Команды Telnet



Команды Telnet

Telnet использует команды в полосе (in-band signaling) в обоих направлениях. Байт 0xff (255 десятичный) называется IAC, "интерпретировать как команду". Следующий байт является командным байтом. Для того чтобы послать байт данных равный 255, отправляются два последовательных байта равных 255. (В предыдущем параграфе мы сказали, что поток данных имеет формат NVT ASCII, то есть используются 7-битные значения, а это означает, что байт данных равный 255 не может быть отправлен посредством Telnet. Существует двоичная опция Telnet, описанная в RFC 856 [Postel and Reynolds 1983b], которая, позволяет передавать 8-битные данные.) На рисунке 26.8 приведены команды Telnet.

Имя Код (десятичный) Описание
EOF 236 конец файла
SUSP 237 подавить текущий процесс (управление задачами)
ABORT 238 прекратить процесс
EOR 239 конец записи
SE 240 конец подопции
NOP 241 пустая операция
DM 242 маркер данных
BRK 243 прерывание
IP 244 прервать процесс
AO 245 прекратить вывод
AYT 246 вы здесь?
EC 247 escape символ
EL 248 стереть строку
GA 249 идем дальше
SB 250 начало подопции
WILL 251 обсуждение опции (рисунок 26.9)
WONT 252 обсуждение опции
DO 253 обсуждение опции
DONT 254 обсуждение опции
IAC 255 байт данных 255


Команды Telnet предваряемые IAC (255)



Рисунок 26.8 Команды Telnet, предваряемые IAC (255).

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



Команды VRFY и EXPN



Команды VRFY и EXPN

Команда VRFY проверяет, в порядке ли адрес получателя, не посылая при этом реальной почты. EXPN предназначена для расширения почтового псевдонима до почтового адреса. Большинство SMTP реализаций (такие как Sendmail) воспринимают эти команды абсолютно одинаково, однако мы уже отмечали, что более новые версии Sendmail проводят различие между ними.

В качестве простого теста мы можем подсоединиться к более новой версии Sendmail и посмотреть эти различия. (Мы удалили вывод клиента Telnet.)


sun % telnet vangogh.cs.berkeley.edu 25
220-vangogh.CS.Berkeley.EDU Sendmail 8.1C/6.32 ready at Tue, 3 Aug 1993 14:59:12 -0700
220 ESMTP spoken here

helo bsdi.tuc.noao.edu
250 vangogh.CS.Berkeley.EDU Hello sun.tuc.noao.edu [140.252.1.29], pleased to meet you

vrfy nosuchname
550 nosuchname... User unknown

vrfy rstevens
250 Richard Stevens <rstevens@vangogh.CS.Berkeley.EDU>

expn rstevens
250 Richard Stevens <rstevens@noao.edu>

Во-первых, обратите внимание на то, что мы специально напечатали неверное имя хоста для команды HELO: bsdi вместо sun. Большинство SMTP серверов берут IP адрес клиента и осуществляют запрос указателя DNS (глава 14, раздел "Запросы указателя"), после чего сравнивают имена хостов. Это позволяет серверу зарегистрировать соединение клиента, основываясь на его IP адресе, а не на имени, которое пользователь может указать неверно. Некоторые серверы отвечают юмористическими сообщениями, такими как "вы шарлатан" или "почему бы вам не позвонить самому себе...". В этом примере мы видели, что сервер просто напечатал реальное имя домена из запроса указателя вместе с IP адресом.

Затем мы вводим команду VRFY для несуществующего имени, на что сервер отвечает ошибкой 550. Затем мы печатаем существующее имя, а сервер отвечает именем пользователя на локальном хосте. Затем мы пробуем команду EXPN и получаем другой отклик. Команда EXPN определяет, что почта для этого пользователя будет перенаправлена и печатает адрес перенаправления.

На многих хостах команды VRFY и EXPN отключены, может быть с точки зрения секретности и иногда из-за того, что администраторы считают, что в этом находится какая-то дырка в секретности. Например, мы можем попробовать воспользоваться этими командами на SMTP сервере Белого Дома (США):


sun % telnet whitehouse.gov 25
220 whitehouse.gov SMTP/smap Ready.

helo sun.tuc.noao.edu
250 (sun.tuc.noao.edu) pleased to meet you.

vrfy clinton
500 Command unrecognized

expn clinton
500 Command unrecognized



Конверты заголовки и тело



Конверты, заголовки и тело

Электронная почта состоит из трех частей. Конверт используется MTA для доставки. В нашем примере конверт был указан двумя SMTP командами:

MAIL From:<rstevens@sun.tuc.noao.edu>
RCPT To:<rstevens@noao.edu>

RFC 821 определяет содержимое и интерпретацию конверта, а также протокол, который используется для обмена почтой по TCP соединению.

Заголовки используются пользовательскими агентами. В примере мы видели девять полей заголовков: Received, Message-Id, From, Date, Reply-To, X-Phone, X-Mailer, To и Subject. Каждое поле заголовка содержит имя, после которого следует двоеточие, а затем следует значение этого поля. RFC 822 определяет формат и интерпретацию полей заголовка. (Заголовки, начинающиеся с X-, это поля, определяемые пользователем. Другие определены в RFC 822.) Длинные поля заголовков, такие как Received в примере, могут быть разбиты на несколько строк, причем дополнительные строки начинаются с пробела. Тело это содержимое сообщения от отправителя к получателю. RFC 822 определяет тело сообщения как текстовые строки в формате NVT ASCII. Когда происходит передача с использованием команды DATA, заголовки передаются первыми, за ними следует пустая строка и затем следует тело сообщения. Каждая строка, передаваемая с использованием команды DATA, должна меньше чем 1000 байт.

Затем пользовательский агент берет то, что было указано в качестве тела сообщения, добавляет некоторые заголовки и передает результат в MTA. MTA добавляет свои заголовки, добавляет конверт и посылает результат другому MTA.

Термин содержимое часто используется, чтобы описать комбинацию заголовков и тела. Содержимое посылается клиентом с использованием команды DATA.



Краткие выводы



Краткие выводы

В этой главе детально рассматривается стратегия TCP тайм-аутов и повторных передач. Наш первый пример был посвящен потерянному SYN, с помощью которого устанавливаются соединения, и мы видели, как применяется экспотенциальное наращивание значений последовательных тайм-аутов при повторной передаче.

TCP рассчитывает время возврата и затем использует полученные значения, чтобы поддерживать и обновлять значение хэшированной оценочной функции RTT и хэшированной оценочной функции среднего отклонения. Эти два показателя затем используются при расчете следующего значения тайм-аута для повторной передачи. Большинство реализаций рассчитывают только один RTT на окно. Алгоритм Карна снимает проблему двусмысленной повторной передачи, поэтому не приходится рассчитывать RTT в случае потери пакета.

Наш подробный пример, в котором было потеряно три пакета, позволил нам рассмотреть большинство алгоритмов TCP в действии: медленный старт, предотвращение переполнения, быструю повторную передачу и быстрое восстановление. Мы также имели возможность рассчитать оценочные функции RTT TCP вместе с окном переполнения и порогом медленного старта, а также сравнить эти значения с реальными значениями, полученными из вывода отладочных программ.

Мы закончили рассмотрением влияния различных ICMP ошибок на TCP соединение, и как TCP позволено перестраивать порядок движения данных. Мы видели, что "мягкие" ICMP ошибки не приводят к разрыву соединения, однако запоминаются таким образом, что когда соединение разрывается по каким-либо причинам, ошибка может быть выведена в виде сообщения.



Краткие выводы

Устойчивый таймер TCP устанавливается одним концом соединения, когда у него есть данные, которые необходимо отправить, однако отправка была остановлена, потому что другой конец соединения объявил окно нулевого размера. Отправитель отправляет пробы окна, при этом интервал повторной передачи рассчитывается так, как это делалось в главе 21. Отправка проб закрытого окна продолжается постоянно.

С помощью примеров, работы устойчивого таймера, мы видели, как TCP борется с синдромом глупого окна. Это необходимо для того, чтобы предотвратить объявление маленьких окон или отправку маленьких пакетов. В примерах мы видели, как происходит предотвращение синдрома глупого окна на обоих концах, то есть у отправителя и получателя.

Упражнения

На рисунке 22.3 обратите внимание на моменты времени соответствующие подтверждениям (сегменты 5, 7, 9, 11, 13, 15 и 17): 0,170; 5,170; 10,170; 15,170; 15,370; 20,170 и 25,170. Также обратите внимание на разницу во времени между получением данных и отправкой подтверждений: 164,5; 18,5; 18,7; 18,8; 198,3; 18,5 и 19,1 миллисекунды. Объясните, что бы это могло означать. На рисунке 22.3 в момент времени 25,174 объявляется окно размером 767, однако в приемном буфере есть место для 768 байт. Чем объясняется разница в 1 байт?

Краткие выводы

Как мы говорили ранее, характеристика "оставайся в живых" довольно спорная. Эксперты, работающие с протоколами, продолжают дебаты по поводу того, принадлежит ли она транспортному уровню или должна должна быть реализована непосредственно в приложении.

Она функционирует посредством отправки пробных пакетов по соединению, после того как соединение не использовалось в течение 2 часов. Могут возникнуть четыре различных сценария: удаленный конец функционирует и откликается, удаленный конец вышел из строя, удаленный конец вышел из строя и перезагрузился и удаленный конец в настоящее время недоступен. В нашем примере мы рассмотрели все эти сценарии и видели различные ошибки, возвращаемые для последних трех условий.

В двух первых примерах только эта характеристика позволила клиенту определить, что другой конец вышел из строя или вышел из строя и перезагрузился. В последнем примере, однако, с удаленным концом ничего не произошло, но соединение между ними было временно разорвано. Мы должны всегда помнить эти ограничения, когда используем опцию "оставайся в живых".





Краткие выводы

В этой главе рассмотрено пять новых характеристик TCP: определение транспортного MTU, опция масштабирования окна, опция временной марки, защита от перехода через 0 номера последовательности и улучшенная обработка транзакций с использованием TCP. Мы видели, что три средние опции требуются для оптимальной производительности в каналах с повышенной пропускной способностью - в сетях с большой емкостью.

Определение транспортного MTU позволяет TCP использовать окна больше, чем окно по умолчанию равное 536, для нелокальных соединений, когда транспортный MTU больше. Это может улучшить производительность.

Опция масштабирования окна воспринимает максимальный размер TCP окна от 65535 байт до сверх 1 гигабайта. Опция временной марки позволяет аккуратно засечь время для нескольких сегментов и также позволяет получателю предоставить защиту против перехода номера последовательности через 0 (PAWS). Это очень важно для высокоскоростных соединений. Эти новые опции TCP обсуждаются хостами при установлении соединения и игнорируются более старыми системами, которые не понимают их, позволяя более новым системам нормально функционировать с более старыми системами.

Расширение TCP для транзакций, T/TCP, позволяет ограничить общение клиент-сервер запрос-отклик всего тремя сегментами. Это позволяет избежать трехразового рукопожатия и уменьшить продолжительность состояния TIME_WAIT с помощью кэширования небольшого количества информации для каждого хоста, с которым установлено соединение. При этом флаги SYN и FIN передаются в сегментах данных.

Мы завершили главу рассмотрением производительности TCP, так как до сих пор существует огромное количество "фольклора", который далек от истины, о том, как может и насколько быстро должен работать TCP. Для хорошо настроенных и отлаженных реализаций, которые используют более новые характеристики, описанные в этой главе, производительность TCP ограничивается только максимальным окном размером в 1 гигабайт и скоростью света (то есть, временем возврата).





Краткие выводы

SNMP это простой протокол, основанный на запросах и откликах, предназначенный для обмена между SNMP менеджером и SNMP агентом. Информационная база данных управления (MIB) определяет переменные, которые обслуживаются агентом, которые, в свою очередь, менеджер может либо запросить, либо установить. Для определения переменных используется ограниченное количество типов данных.

Все переменные идентифицируются идентификаторами объекта, используется иерархическая схема присвоения имен, которая состоит из длинных строк чисел, которые обычно сокращаются в простые имена, для простоты чтения. Конкретные переменные строятся с помощью добавления переменной к идентификатору объекта.

Большинство SNMP переменных содержится в таблицах, с фиксированными номерами колонок, однако с переменными номерами строк. Фундаментальным для SNMP является схема идентификации, используемая для того, чтобы идентифицировать каждую строку в таблице (в том случае, когда мы не знаем, сколько строк содержится в таблице), и лексикографический порядок (порядок колонка-строка). SNMP оператор get-next является основным для любого SNMP менеджера.

Мы описали следующие группы SNMP переменных: система, интерфейс, трансляция адресов, IP, ICMP, TCP и UDP. Затем показали два примера, один из которых позволил определить MTU интерфейса, а другой - просмотреть таблицу маршрутизации маршрутизатора.

Мы завершили главу рассмотрением SNMP ловушек. Это способ, предоставляющий агенту возможность уведомить менеджера о том, что произошло какое-либо событие, которое будет интересно менеджеру. Здесь же кратко описаны ASN.1 и BER. Две последние темы, скорее всего, являются наиболее сложными аспектами SNMP, однако они необходимы только для разработчиков.

Упражнения

Мы сказали, что использование двух различных портов (161 и 162) позволяет системе запускать как менеджера, так и агента. Что произойдет, если будет использоваться один и тот же порт? Как Вы можете получить полный список таблицы маршрутизации с использованием get-next?

Назад

Компания | Услуги | Для клиентов | Библиотека | Галерея | Cофт | Линки

На главную





Краткие выводы

В этой главе показано функционирование приложений Rlogin и Telnet. Оба предоставляют заход удаленным терминалом с хоста клиента на хост сервера, а также позволяют запускать программы на сервере.

Между этими приложениями существуют отличия. Rlogin подразумевает, что на обоих концах соединения присутствуют Unix хосты, поэтому существует только одна опция. Это простой протокол. Telnet не ограничивает, какая операционная система используется на обоих концах соединения. Telnet разработан для того, чтобы функционировать между различными операционными системами.

Чтобы поддерживать разнородное окружение, Telnet предоставляет обсуждение опций между клиентом и сервером. Это позволяет общаться клиентам и серверам, а также позволяет добавлять новые опции.

Мы рассмотрели процесс обсуждения опций Telnet и видели, что три типа передачи данных: символ за один раз, строка за раз и реальный линейный режим. Сегодня существует тенденция по направлению ко вводу строки за раз, когда это возможно, чтобы уменьшить сетевой траффик и обеспечить лучший отклик интерактивному пользователю при редактировании строк и отражения введенного эхом.

На рисунке 26.18 сравниваются различные характеристики, предоставляемые Rlogin и Telnet.

Характеристика Rlogin Telnet
транспортный протокол Одно TCP соединение. Используется режим срочности. Одно TCP соединение. Используется режим срочности.
пакетный режим Всегда символ за один раз, удаленное эхо. Общий режим по умолчанию - символ за один раз, удаленное эхо. Поддерживается режим строки за раз с эхом от клиента. Новые опции для реального линейного режима с эхом от клиента. Если приложение на сервере требует режим символ за один раз - он поддерживается всегда.
управление потоком данных Обычно осуществляется клиентом, однако может быть выключено сервером. Обычно осуществляется сервером, иногда позволяется делать клиенту.
тип терминала Присутствует всегда. Опционально, обычно поддерживается.
скорость терминала Присутствует всегда. Опционально.
размер окна Опционально поддерживается большинством серверов. Опционально.
переменные окружения Не поддерживается. Опционально.
автоматический login По умолчанию. Может появиться приглашение ввести пароль, который посылается в виде открытого текста. Более новые версии поддерживают Kerberos. По умолчанию необходимо ввести имя и пароль, который отправляется в виде открытого текста. Более новыми версиями предоставляется опция аутентификации.




Краткие выводы

FTP это стандарт, признанный в Internet, для передачи файлов. В отличие от большинства других TCP приложений, он использует два TCP соединения между клиентом и сервером - управляющее соединение, которое существует в течение всего продолжения сессии клиент-сервер, и соединение данных, которое создается и удаляется по необходимости.

Управление соединением, которое осуществляется FTP, позволило нам увидеть, какие требования выдвигает TCP к управлению соединением. Мы видели состояние ожидания 2MSL на клиенте, который не выдает команды PORT.

FTP использует формат NVT ASCII для всех команд и откликов, которые передаются по управляющему соединению. Режим передачи данных по умолчанию это, как правило, также NVT ASCII. Мы видели, что более новые Unix клиенты автоматически посылают команду, чтобы убедиться в том, что сервер это Unix хост с 8-битными байтами, и если так, используют двоичный режим для передачи всех файлов, которые являются более эффективными.

Также мы показали пример анонимного FTP, популярного способа распространения программного обеспечения по Internet.





Краткие выводы

В работе электронной почты принимают участие пользовательские агенты на обоих концах (отправитель и получатель), а также два или несколько агентов передачи сообщения. Мы можем поделить почтовое сообщение на три части: конверт, заголовки и тело сообщения. Мы видели, как происходит обмен этими частями с использованием SMTP, который является стандартом в Internet. Все три состоят из символов NVT ASCII.

Также мы рассмотрели новые расширения этих трех частей: расширенный SMTP для конверта, не-ASCII заголовки и дополнительная структура для тела сообщения с использованием MIME. Структура и кодирование, используемые MIME, позволяют обмениваться двоичными данными с использованием существующих 7-битных MTA SMTP.





Краткие выводы

RPC это способ построить приложение клиент-сервер таким образом, что клиент просто вызывает процедуры на сервере. Все сетевые детали спрятаны в stubах клиента и сервера, которые генерируются для приложений пакетом RPC и в подпрограммах библиотеки RPC. Мы показали формат RPC сообщений вызова и отклика и упомянули, что XDR используется, чтобы кодировать значения, что позволяет RPC клиентам и серверам работать на машинах с различной архитектурой.

Одно из наиболее широко используемых приложений RPC это Sun NFS, протокол доступа к разнородным файлам, который широко используется на хостах практически всех размеров. Мы рассмотрели NFS и то, как он использует UDP или TCP. В протоколе NFS версии 2 (NFS Version 2) определено 15 процедур.

Доступ клиента к NFS серверу начинается с протокола монтирования, после чего клиенту возвращается описатель файла. Затем клиент может получить доступ к файлам в файловой системе сервера с использованием этого описателя файла. Имена файлов просматриваются на сервере по одному элементу имени за раз, при этом для каждого элемента возвращается новый описатель файла. Конечный результат это описатель того файла, к которому было осуществлено обращение, и который используется при последовательных чтениях и записях.

NFS старается сделать все свои процедуры независимыми от количества исполнений таким образом, чтобы клиент мог просто повторно выдать запрос, если отклик был потерян. Мы видели примеры этого: в случае, когда клиент читал файл, пока сервер вышел из строя и перезагружался.





Краткие выводы

Первые два приложения, которые мы рассмотрели, Finger и Whois, предназначены для получения информации о пользователях. Клиент Finger запрашивает сервер, чаще всего для того, чтобы найти какое-либо имя (например, чтобы отправить пользователю почту) или для того чтобы посмотреть, зашел ли кто-либо в систему терминалом в настоящий момент. Клиент Whois обычно общается с сервером, запущенным от InterNIC, в поисках информации о человеке, организации, домене или номере сети.

Другие сервисы, позволяющие более эффективно работать с ресурсами Internet, это Archie, WAIS, Gopher, Veronica и WWW. Они помогают найти в Internet файлы и документы. В настоящее время разрабатываются и другие средства определения ресурсов.

Эта глава закончена кратким рассмотрением системы X Window System, еще одного очень "серьезного" приложения, работающего с TCP/IP. Мы видели, что X сервер обслуживает несколько окон на дисплее и обеспечивает общение клиента с его окном. С помощью программы Xscope мы видели, как существует возможность поместить еще одну программу между клиентом и сервером, чтобы получить информацию о том, с помощью каких сообщений осуществляется обмен.



Краткое описание характеристик предоставляемых Rlogin и Telnet



Рисунок 26.18 Краткое описание характеристик, предоставляемых Rlogin и Telnet.

Telnet и Rlogin серверы обычно устанавливают TCP опцию "оставайся в живых" (keepalive) (глава 23), если она поддерживается реализацией TCP сервера, чтобы определить момент выхода из строя хоста клиента. Оба приложения также используют режим срочности TCP, чтобы посылать команды сервера клиенту, даже если поток данных в этом направлении был остановлен управлением потока данных.



LBX X с низкой шириной полосы



LBX: X с низкой шириной полосы

Кодирование, используемое протоколом X, оптимально для работы в локальных сетях, где время, которое тратится на кодирование и декодирование данных, более важно, нежели минимизация количества передаваемых данных. При работе с Ethernet все нормально, однако в случае медленных последовательных каналов, таких как SLIP и PPP (глава 2, разделы "SLIP: IP по последовательной линии" и "PPP: протокол точка-точка") возникают проблемы.

Поэтому был разработан стандарт Low Bandwidth X (LBX), который использует следующую технику для уменьшения сетевого траффика: кэширование, отправку изменений от предыдущих пакетов и сжатие. Спецификации появились в 1993 году с реализацией X window system Release 6.



Лексикографический порядок



Лексикографический порядок

Порядок в MIB основан на расположении идентификаторов объектов. Все записи в MIB таблице расположены в лексикографическом порядке в соответствии с их идентификаторами объектов. Это означает, что шесть переменных, приведенных на рисунке 25.12, расставлены в MIB так, как это показано на рисунке 25.13. В результате можно декларировать два правила.

Строка (ряд) Идентификатор объекта Сокращенное имя Значение
1 1.3.6.1.2.1.7.5.1.1.0.0.0.0.67
1.3.6.1.2.1.7.5.1.2.0.0.0.0.67
udpLocalAddress.0.0.0.0.67
udpLocalPort.0.0.0.0.67
0.0.0.0
67
2 1.3.6.1.2.1.7.5.1.1.0.0.0.0.161
1.3.6.1.2.1.7.5.1.2.0.0.0.0.161
udpLocalAddress.0.0.0.0.161
udpLocalPort.0.0.0.0.161
0.0.0.0
161
3 1.3.6.1.2.1.7.5.1.1.0.0.0.0.520
1.3.6.1.2.1.7.5.1.2.0.0.0.0.520
udpLocalAddress.0.0.0.0.520
udpLocalPort.0.0.0.0.520
0.0.0.0
520


Лексикографический порядок таблицы слушающего процесса UDP



Рисунок 25.13 Лексикографический порядок таблицы слушающего процесса UDP.

Так переменная udpLocalAddress всегда появляется перед появлением в этой же таблице следующей переменной (udpLocalPort), это означает, что доступ к таблице осуществляется в порядке колонка-строка. Это является результатом лексикографического упорядочивания идентификаторов объектов, а не имен, предназначенных для чтения человеком. Порядок расположения строк в таблице зависит от значений индексов для таблицы. На рисунке 25.13, 67 лексикографически меньше чем 161, который, в свою очередь, лексикографически меньше чем 520.

На рисунке 25.14 показан порядок колонка-строка для нашего примера таблицы слушающего процесса UDP.



Линейный режим (Linemode)



Линейный режим (Linemode)

Чтобы увидеть опцию линейного режима Telnet в действии, мы запустим клиента на хосте bsdi и подключимся к серверу 4.4BSD на vangogh.cs.berkeley.edu. И BSD/386, и 4.4BSD поддерживают эту опцию.

Мы не будем рассматривать все пакеты или обсуждаемые опции и подопции, потому что оно подобно тому, что мы привели в предыдущем примере. Вместо этого рассмотрим особенности обсуждения этой опции.

Сервер 4.4BSD поддерживает больше опций, доступных к обсуждению, чем BSD/386: размер окна, локальное управление потоком данных, состояние опций, прием переменных окружения и скорость терминала. Сервер 4.4BSD старается обсудить более новые опции, чем те, которые поддерживаются клиентом BSD/386: аутентификация (позволяет избежать отправки пользовательского пароля в виде открытого текста по соединению). Клиент посылает опцию WILL LINEMODE, сервер отвечает DO LINEMODE, так как он поддерживает эту опцию. Клиент отправляет серверу 16 специальных символов в качестве подопции. Это текущие значения специальных символов терминала на хосте клиента: символ прерывания, символ конца файла и так далее. Сервер отправляет подопции клиенту, которые сообщают ему, как обрабатывать все входные строки и как осуществлять все функции редактирования (удаление символа, удаление строки и так далее). Клиент отправляет серверу только завершенные строки. Сервер также сообщает клиенту, как транслировать любые символы прерывания или сигнальные символы в соответствующие символы Telnet. Например, если символ прерывания - Control-C, и мы вводим Control-C, чтобы прервать текущий процесс на сервере, клиент посылает серверу Telnet команду "прервать процесс" (<IAC, IP>). Интересно посмотреть, что происходит, когда мы вводим пароль. В случае Rlogin или режима Telnet один символ за раз, когда сервер осуществляет эхо, он не отражает эхом символы пароля. В случае линейного режима, однако, эхо осуществляется самим клиентом. Он справляется с этой задачей с помощью следующего обмена: (a) Сервер отправляет WILL ECHO, сообщая клиенту, что сервер будет осуществлять отражение эхом. (b) Клиент отвечает DO ECHO. (c) Сервер отправляет строку Password: клиенту, а клиент выводит эту строку на терминал. (d) Мы вводим пароль, клиент посылает его серверу при нажатии клавиши RETURN. Пароль не отражается эхом, так как клиент считает, что это сделает сервер. (e) Сервер посылает 2-байтовую последовательность CR, LF, чтобы переместить курсор, так как символ RETURN, который завершил ввод пароля, не был отображен эхом. (f) Сервер посылает WONT ECHO. (g) Клиент отвечает DONT ECHO. Клиент восстанавливает отражение эхом.

После того как мы зашли удаленным терминалом, клиент строит полные строки и отправляет их серверу. Это и есть назначение опции линейного режима. Она уменьшает количество сегментов, которыми обмениваются клиент и сервер, а также предоставляет более быстрый отклик на введенные клиентом символы, (например, эхо и редактирование). На рисунке 26.14 показан обмен пакетами, при вводе команды

vangogh % date

по Telnet соединению с использованием линейного режима. (Мы удалили всю информацию о типе сервиса и объявления окна.)



Линейный режим символ прерывания от клиента



Линейный режим: символ прерывания от клиента

Давайте посмотрим, что делает Telnet, когда клиент вводит символ прерывания. Мы открыли сессию между клиентом bsdi и сервером vangogh.cs.berkeley.edu. На рисунке 26.17 показана временная диаграмма того, что происходит, когда вводится символ прерывания. (Мы удалили объявления окна и тип сервиса.)

В сегменте 1 символ прерывания (обычно Control-C или DELETE) конвертируется в команду Telnet "прерывание процесса" (IP - interrupt process): <IAC, IP>. Следующие 3 байта, <IAC, DO, TM>, содержат опцию Telnet DO TIMING MARK. Эта метка отправляется клиентом и на нее должен быть получен ответ либо WILL, либо WONT. В любом случае все данные получены от сервера, перед тем как выдается отклик (за исключением команд Telnet). Это метка синхронизации от клиента к серверу и обратно. Сегмент 1 не посылается с использованием режима срочности TCP.



Ловушки (Traps)



Ловушки (Traps)

Все примеры, которые мы рассмотрели в этой главе, иллюстрируют передачу информации от менеджера к агенту. Однако у агента существует способ сообщить менеджеру о возникновении какого-либо события, о котором менеджер должен знать (см. рисунок 25.1). В этом случае агент посылает менеджеру ловушки (trap). Ловушки отправляются на UDP порт 162 менеджера.

На рисунке 25.2 мы показали формат ловушки PDU. Мы просмотрим все поля в этом сообщении, когда ниже будем рассматривать вывод команды tcpdump.

Определены шесть ловушек, седьмая используется производителем, чтобы установить собственную ловушку. На рисунке 25.30 описываются значения типа ловушки (trap type) в сообщении ловушки (рисунок 25.2).

тип ловушки Имя Описание
0 coldStart Агент инициализировал себя сам.
1 warmStart Агент повторно инициализировал себя сам.
2 linkDown Состояние интерфейса изменилось с "активизировано" на "выключено" (рисунок 25.18). Первая переменная в сообщении указывает на интерфейс.
3 linkUp Состояние интерфейса изменилось с состояния "выключено" на состояние "активизировано" (рисунок 25.18). Первая переменная в сообщении указывает на интерфейс.
4 authenticationFailure Сообщение было получено от SNMP менеджера из неверного сообщества.
5 egpNeighborLoss EGP узел изменил свое состояние на "выключено". Первая переменная в сообщении содержит IP адрес узла.
6 enterpriseSpecific Обратитесь к полю специализированных кодов за информацией об этой ловушке.


Медленный старт



Медленный старт

Мы описали алгоритм медленного старта в разделе "Медленный старт" главы 20, а также видели его в действии на рисунке 21.2.

Первоначально по соединению отправляется только один сегмент, и подтверждение на него должно быть получено перед тем, как будет отправлен другой сегмент. Когда сегмент 2 принят, отправляются два следующих сегмента.



Медленный старт и предотвращение переполнения



Рисунок 21.8 Медленный старт и предотвращение переполнения.


На этом рисунке мы предположили, что переполнение возникает, когда cwnd имеет значение равное 32 сегментам. ssthresh устанавливается в 16 сегментов, а cwnd устанавливается в 1 сегмент. Один сегмент посылается в момент времени 0 и предполагается, что ACK на него возвращается в момент времени 1, cwnd увеличивается до 2 сегментов. Затем отправляется два сегмента и предполагается, что их ACK прибывают в момент времени 2, cwnd увеличивается до 4 сегментов (по одному разу на каждый ACK). Этот экспотенциальный рост продолжается до тех пор, пока cwnd не будет равно ssthresh, а именно после того как 8 ACK были приняты между моментами времени 3 и 4. С этой точки увеличение cwnd линейное, причем максимальный увеличение - это увеличение на один сегмент за период равный времени возврата.

Как видно из этого рисунка, термин "медленный старт" не вполне корректен. Это, скорее, замедление передачи пакетов, которое вызвано переполнением, однако скорость увеличения количества пакетов, отправленных в сеть, увеличивается в течение медленного старта. Скорость увеличения не уменьшается до тех пор, пока не будет достигнуто значение ssthresh, когда начинает действовать предотвращение переполнения.



Монтирование директории bsdi /usr как /nfs/bsdi/usr на хосте sun



Рисунок 29.6 Монтирование директории bsdi:/usr как /nfs/bsdi/usr на хосте sun.


После чего при обращении к файлу /nfs/bsdi/usr/rstevens/hello.c на клиенте sun, происходит обращение к файлу /usr/rstevens/hello.c на сервере bsdi.



MTU интерфейса



MTU интерфейса

Вернемся к нашему эксперименту, описанному в разделе "ICMP ошибки о недоступности" главы 11, в котором мы пытались определить MTU SLIP канала от netb к sun. Сейчас мы можем использовать SNMP, чтобы получить этот MTU. Во-первых, мы получим номер интерфейса (ipRouteIfIndex) для SLIP канала (140.252.1.29) из таблицы IP маршрутизации. Для этого, мы попадаем в таблицу интерфейсов и получаем MTU (вместе с описанием и типом) канала SLIP:

sun % snmpi -a netb -c secret

snmpi> get ipRouteIfIndex.140.252.1.29
ipRouteIfIndex.140.252.1.29=12
snmpi> get ifDescr.12 ifType.12 ifMtu.12
ifDescr.12="Telebit NetBlazer dynamic dial virtual interface"
ifType.12=other(1)
ifMtu.12=1500

Мы видим, что даже для канала, который является SLIP, MTU установлено в Ethernet значение равное 1500, возможно для того, чтобы избежать фрагментации.



MX записи хосты которые выключены



MX записи: хосты, которые выключены

Другое использование MX записи заключается в том, чтобы найти альтернативного получателя почты, если хост назначения выключен. Если мы посмотрим DNS записи для нашего хоста sun, то увидим, что он имеет две MX записи:


sun % host -a -v -t mx sun.tuc.noao.edu
sun.tuc.noao.edu 86400 IN MX 0 sun.tuc.noao.edu
sun.tuc.noao.edu 86400 IN MX 10 noao.edu
Additional information:
sun.tuc.noao.edu 86400 IN A 140.252.1.29
sun.tuc.noao.edu 86400 IN A 140.252.13.33
noao.edu 86400 IN A 140.252.1.54

MX запись с минимальным уровнем предпочтительности указывает, что сначала надо попробовать доставить почту непосредственно на хост. Следующее значение предпочтительности указывает на необходимость осуществить доставку почты на хост noao.edu.

В следующем скрипте мы посылаем почту сами себе на хост sun.tuc.noao.edu, с хоста vangogh.cs.berkeley.edu, предварительно выключив SMTP сервер назначения. Когда на порт 25 прибывает запрос на соединение, TCP должен ответить сбросом (RST), так как не существует процесса, который может осуществить пассивное открытие для этого порта.


vangogh % mail -v rstevens@sun.tuc.noao.edu
A test to a host that's down.
.

EOT

rstevens@sun.tuc.noao.edu...Connecting to sun.tuc.noao.edu.(smtp)...
rstevens@sun.tuc.noao.edu...Connecting to noao.edu.(smtp)...

220 noao.edu ...
дальше идет обычная передача почты SMTP

Мы видим, что MTA старается установить контакт с sun.tuc.noao.edu, затем прекращает попытки и устанавливает контакт с noao.edu.

На рисунке 28.5 показан вывод команды tcpdump, где показано, как TCP отвечает сбросом (RST) на входящие SYN.


1 0.0 vangogh.3873 > 140.252.1.29.25: S 2358303745:2358303745(0) ...
2 0.000621 (0.0006) 140.252.1.29.25 > vangogh.3873: R 0:0(0) ack 2358303746 win 0

3 0.300203 (0.2996) vangogh.3874 > 140.252.13.33.25: S 2358367745:2358367745(0) ...
4 0.300620 (0.0004) 140.252.13.33.25 > vangogh.3874: R 0:0(0) ack 2358367746 win 0



Начальное обсуждение опций Telnet клиентом и сервером



Рисунок 26.12 Начальное обсуждение опций Telnet клиентом и сервером.

Строки, в которых происходит обсуждение опций, пронумерованы (они начинаются с SENT или RCVD). Давайте рассмотрим обсуждение опций более подробно. Клиент начинает с обсуждения опции SUPPRESS GO AHEAD. Эта опция начинается с DO, так как команда GO AHEAD обычно отправляется от сервера клиенту, и клиент хочет, чтобы сервер включил опцию. (Это немного непонятно, так как включение опции исключает отправку команд GA.) Сервер соглашается на включение этой опции в строке 10. Клиент хочет отправить свой тип терминала как указано в RFC 1091 [VanBokkelen 1989]. Это является обычным для Unix клиентов. Опция начинается с WILL, так как клиент хочет включить эту опцию для себя. NAWS означает "обсуждение размера окна", как определено в RFC 1073 [Waitzman 1988]. Если сервер согласен (чего не происходит в строке 11), клиент посылает подопцию с количеством строк и колонок своего терминала. Если размер окна изменяется, клиент пошлет эту подопцию позже. (То же самое мы видели в случае Rlogin с командой 0x80 на рисунке 26.4.) Опция TSPEED позволяет отправителю (обычно клиенту) сообщить свою скорость терминала, как определено в RFC 1079 [Hedrick 1988b]. Если сервер согласен (чего не происходит в строке 12), то клиент отправляет подопцию, в которой сообщает свою скорость передачи и скорость приема. LFLOW обозначает "локальное управление потоком данных", как определено в RFC 1372 [Hedrick and Borman 1992]. Клиент отправляет эту опцию серверу, сообщая, хочет ли он включить или выключить управление потоком данных. Если сервер согласен (чего не происходит в строке 13), сервер посылает подопцию клиенту, в которой сообщается, что переключение между клиентом и сервером будет осуществляться с помощью Control-S и Control-Q. (Это напоминает то, что мы видели в случае Rlogin команд 0x10 и 0x20 на рисунке 26.4.) Как мы уже говорили, обсуждая Rlogin, пользователь получает лучшее управление потоком данных, когда оно осуществляется клиентом, а не сервером. LINEMODE это реальный линейный режим, о котором мы уже упоминали в разделе "Протокол Telnet". Вся обработка символов введенных с терминала осуществляется Telnet клиентом (удалить символ, удалить строку и так далее), а серверу отправляются завешенные строки. Ниже мы увидим, как это делается. Эта опция отклонена в строке 14. Опция ENVIRON позволяет клиенту отправить переменные окружения серверу, как определено в RFC 1408 [Borman 1993a]. При этом переменные окружения с хоста клиента могут быть автоматически установлены на хосте сервера. Сервер отказался активизировать эту опцию в строке 15. ( В соответствии с соглашением, переменные окружения в Unix - это имена из заглавных букв, после которых через знак равно, следует значение переменной, однако это всего лишь соглашение.) По умолчанию, Telnet клиент BSD/386 посылает только две переменные, а именно DISPLAY и PRINTER, если они определены и если опция включена. Пользователь Telnet может указать дополнительные переменные окружения, которые необходимо отправить. Опция STATUS (RFC 859 [Postel and Reynolds 1983e]) позволяет одному участнику обмена спросить другой о его текущем состоянии опций Telnet. В этом примере клиент просит сервер включить опцию (DO). Если сервер согласен (чего не происходит в строке 16), клиент может в подопции попросить сервер послать статус его опций. Это первый отклик от сервера. Сервер согласен включить опцию типа терминала. (Почти каждый Unix сервер поддерживает эту опцию.) Клиент, однако, не может послать свой тип терминала, пока сервер не попросит его об этом с помощью подопции (строка 17). Сервер согласен запретить отправку команды GO AHEAD. Сервер не позволяет клиенту отправить свой размер окна. Сервер не позволяет клиенту отправить свою скорость терминала. Сервер не позволяет клиенту осуществлять управление потоком данных. Сервер не позволяет клиенту включить опцию линейного режима. Сервер не позволяет клиенту послать переменные окружения. Сервер не будет посылать информацию о состоянии своих опций. Это подопция, с помощью которой сервер просит клиента послать тип терминала. Клиент посылает свой тип терминала в виде 6-символьной строки IBMPC3. Сервер просит клиента позволить ему осуществлять отражение эхом. Это первый момент, когда сервер инициирует обсуждение опции. Клиент позволяет серверу осуществлять отражение эхом. Сервер просит клиента осуществлять отображение эхом. Эта команда может показаться лишней, так как подобное обсуждение было предпринято в двух предыдущих строках. Это всего лишь еще один способ, применяемый в большинстве Unix систем, с помощью которого Telnet сервер определяют, является ли их клиент хостом 4.2BSD или более поздним релизом BSD. Если клиент ответит WILL ECHO, он, возможно, является хостом с более поздним релизом чем 4.2BSD и не сможет корректно поддерживать режим срочности TCP. (В этом случае режим срочности не используется.) Клиент отвечает WONT ECHO, из чего следует, что это хост не 4.2BSD. Сервер отвечает на принятое WONT ECHO с DONT ECHO.

На рисунке 26.13 показана временная диаграмма для этого обмена клиент-сервер. (Мы удалили все, связанное с установлением соединения.)

В сегменте 1 содержатся строки 1-8 (рисунок 26.12). Каждая опция занимает 3 байта в сегменте, состоящем из 24 байт. Обсуждение опций начинает клиент. Мы видим, что в одном TCP сегменте может находиться несколько Telnet опций.

Сегмент 3 соответствует строке 9 на рисунке 26.12, команда DO TERMINAL TYPE. Сегмент 5 содержит восемь откликов от сервера на предложенные опции, строки 10-17 (рисунок 26.12). Длина этого сегмента составляет 27 байт, потому что строки 10-16 это стандартные опции, каждая требует 3 байта вместе с подопцией (строка 17), которая требует 6 байт. 12 байт в сегменте 6 соответствуют строке 18, клиент посылает подопцию со своим типом терминала.

Сегмент 8 (53 байта) - это комбинация двух команд Telnet с 47 байтами данных, которые выводятся на терминал. Первые 6 байт - это две команды от сервера: WILL ECHO и DO ECHO (строки 19 и 21). Следующие 47 байт выглядят так:

\r\n\r\nUNIX(r) System V Release 4.0 (svr4) \r\n\r\0\r\n\r\0

Первые 4 байта генерируют две пустые строки, перед тем как эта строка появится в выводе. 2-байтовая последовательность \r\n - это символ новой строки в Telnet. 2-байтовая последовательность \r\0 соответствует символу возврата каретки. Этот сегмент показывает, что данные и команды могут находиться в одном и том же сегменте. Telnet клиент и Telnet сервер должны просматривать каждый полученный байт в поисках IAC байта и затем обрабатывать то, что следует за этим байтом.



Рисунок 26.13 Начальное обсуждение опций Telnet клиентом и сервером.


В сегменте 9 содержатся две последние опции от клиента: строки 20 и 22. Отклик в сегменте 10 соответствует строке 23 - это последняя опция от сервера.

С этого момента по соединению начинается обмен данными. Ничего не мешает тому, чтобы продолжить обсуждение опций, однако этого не происходит. Сегмент 12 содержит приглашение login: от сервера. Сегмент 14 это первый символ, который мы вводим в качестве нашего имени, его эхо возвращается в сегменте 15. Подобный тип интерактивного траффика мы видели в разделе "Интерактивный ввод" главы 19 в случае Rlogin: клиент посылает один символ за один раз, а сервер осуществляет эхо.

Обсуждение опций на рисунке 26.12 инициировано клиентом, однако в нашей книге мы не раз использовали Telnet клиента, чтобы подсоединиться к стандартным серверам, таким как сервер времени или эхо сервер, для того чтобы продемонстрировать различные характеристики TCP. Когда мы рассматривали обмен пакетами в этих примерах, как, например, на рисунке 18.1, то никогда не видели, чтобы клиент инициировал обсуждение опций. Почему? Unix Telnet клиент никогда не начинает обсуждение опций, если указан номер порта, отличный от стандартного порта Telnet (23). Это позволяет Telnet клиенту с использованием стандартного NVT обмениваться данными с другими, не-Telnet серверами. Мы пользовались этим с daytime, echo и discard серверами и будем использовать это с FTP и SMTP серверами в следующих главах.



Несколько одинаковых процедур



Несколько одинаковых процедур

RPC процедуры могут быть исполнены сервером несколько раз, но при этом все равно возвращают тот же самый результат. Например, процедура чтения NFS. Как мы видели на рисунке 29.9, клиент просто повторно выдает вызов READ до тех пор, пока он получает отклик. В нашем примере причина повторной передачи была в том, что сервер вышел из строя. Если сервер не вышел из строя, а сообщения, содержащие RPC отклики, были потеряны (так как UDP ненадежный протокол), клиент просто повторно передает, и сервер снова осуществляет то же самое чтение (READ). Та же самая часть того же самого файла считывается снова и посылается клиенту.

Это работает, потому что каждый запрос на чтение READ содержит начальное смещение. Если бы NFS процедура попросила сервер считать следующие N байт файла, это бы не сработало. Если бы сервер не был безразличным (это значение наоборот к безразличности), и отклик потерян, а клиент повторно выдает READ для следующих N байт, результат будет отличаться. Именно поэтому процедуры NFS READ и WRITE имеют начальное смещение. Именно клиент поддерживает состояние (текущее смещение для каждого файла), а не сервер.

К несчастью, не все операции с файловыми системами можно исполнить несколько раз. Например, представьте себе следующие шаги: клиент NFS выдает запрос REMOVE, чтобы удалить файл; NFS сервер удаляет файл и отвечает OK; отклик сервера потерян; NFS клиент отрабатывает тайм-аут и повторно передает запрос; NFS сервер не может найти файл и возвращает ошибку; приложение клиента получает ошибку, сообщающую о том, что файл не существует. Эта ошибка возвращается приложению клиента, и эта ошибка несет неверную информацию - файл не существовал и был удален.

Ниже приведен список NFS процедур, которые можно исполнить несколько раз: GETATTR, STATFS, LOOKUP, READ, WRITE, READLINK и READDIR. Процедуры, которые нельзя исполнить несколько раз: CREATE, REMOVE, RENAME, LINK, SYMLINK, MKDIR и RMDIR. SETATTR обычно исполняется несколько раз, если только она не была использована для того, чтобы обрезать файл.

Так как в случае использования UDP всегда могут появиться потерянные отклики, NFS сервера должны иметь способ обработать операции, которые нельзя исполнять несколько раз. Большинство серверов имеют кэш последних откликов, в котором они хранят последние принятые отклики для подобных операций. Каждый раз, когда сервер получает запрос, он, во-первых, просматривает свой кэш, и если найдено совпадение, возвращает предыдущий отклик, вместо того чтобы вызывать NFS процедуру снова. [Juszczak 1989] описывает детали этих типов кэша.

Подобный подход к процедурам на серверах применяется ко всем приложениям, основанным на UDP, а не только NFS. DNS, например, предоставляет сервис, безболезненно используемый несколько раз. DNS сервер может осуществить запрос разборщика любое количество раз, что не приведет к отрицательным результатам (может быть, кроме того, что будут заняты сетевые ресурсы).



NFS поверх TCP



NFS поверх TCP

Реализация NFS Berkeley Net/2 поддерживает как UDP, так и TCP. [Macklem 1991] описывает эту реализацию. Давайте рассмотрим, чем отличается использование NFS при работе поверх TCP.

Когда сервер загружается, он запускает NFS сервер, который осуществляет активное открытие на TCP порт 2049, ожидая прихода запроса на соединение от клиента. Это обычно делается в дополнение к обычному NFS UDP, который ожидает входящие датаграммы на UDP порте 2049. Когда клиент монтирует файловую систему сервера с использованием TCP, он осуществляет активное открытие на TCP порт 2049 на сервере. При этом устанавливается TCP соединение между клиентом и сервером для этой файловой системы. Если тот же самый клиент монтирует еще одну файловую систему на том же самом сервере, создается еще одно TCP соединение. И клиент, и сервер устанавливают TCP опцию "оставайся в живых" на своих концах соединения (глава 23). Это позволяет определить момент выхода из строя или перезагрузки того или иного участника обмена. Все приложения на клиенте, которые используют файловую систему сервера, делят одно и то же TCP соединение для этой файловой системы. Например, если была на рисунке 29.6, бы еще одна директория на bsdi, с именем smith, ниже директории /usr, обращения к файлам в /nfs/bsdi/usr/rstevens и /nfs/bsdi/usr/smith делили бы одно и то же TCP соединение. Если клиент определяет, что сервер вышел из строя или перезагрузился (после получения TCP ошибки "соединение закрыто по тайм-ауту" или "соединение закрыто хостом"), он старается повторно подсоединиться к серверу. Клиент осуществляет еще одно активное открытие, чтобы повторно установить TCP соединение для этой файловой системы. Любой запрос от клиента, для которого отработан тайм-аут на предыдущем соединении, повторно выдается на новое соединение. Если клиент вышел из строя, то же происходит и с приложениями, которые работали до выхода из строя. Когда клиент перезагружается, он, возможно, повторно смонтирует файловую систему сервера с использованием TCP, причем будет использовано другое TCP соединение с сервером. Предыдущее соединение между клиентом и сервером для этой файловой системы находится в полуоткрытом состоянии (сервер думает, что оно все еще открыто), однако так как сервер установил опцию "оставайся в живых", это полуоткрытое соединение будет закрыто, когда TCP сервер пошлет следующую пробу "оставайся в живых".

Со временем и другие производители планируют начать поддержку NFS поверх TCP.



В течение 1994 года были



NFS версии 3

В течение 1994 года были выпущены спецификации для версии 3 протокола NFS [Sun Microsystems 1993]. Реализации, как ожидается, станут доступными в течение 1994 года.

Здесь вкратце описаны основные различия между версиями 2 и 3. Мы будем называть их V2 и V3.

Описатели файлов в V2 это массив фиксированного размера - 32 байта. В V3 это массив переменного размера с размером до 64 байт. Массив переменной длины в XDR определяется 4-байтным счетчиком, за которым следуют реальные байты. Это уменьшает размер описателя файла в таких реализациях, как, например, Unix, где требуется всего около 12 байт, однако позволяет не-Unix реализациям обмениваться дополнительной информацией. V2 ограничивает количество байт на процедуры READ или WRITE RPC размером 8192 байта. Это ограничение не действует в V3, что, в свою очередь, означает, что с использованием UDP ограничение будет только в размере IP датаграммы (65535 байт). Это позволяет использовать большие пакеты при чтении и записи в быстрых сетях. Размеры файлов и начальное смещение байтов для процедур READ и WRITE расширены с 32 до 64 бит, что позволяет работать с файлами большего размера. Атрибуты файла возвращаются в каждом вызове, который может повлиять на атрибуты. Это уменьшает количество вызовов GETATTR, требуемых клиентом. Записи (WRITE) могут быть асинхронными, тогда как в V2 они должны были быть синхронными. Это может улучшить производительность процедуры WRITE. Одна процедура была удалена (STATFS) и семь были добавлены: ACCESS (проверка прав доступа к файлу), MKNOD (создание специального файла Unix), READDIRPLUS (возвращает имена файлов в директории вместе с их атрибутами), FSINFO (возвращает статистическую информацию о файловой системе), FSSTAT (возвращает динамическую информацию о файловой системе), PATHCONF (возвращает POSIX.1 информацию о файле) и COMMIT (передает ранее сделанные асинхронные записи на постоянное хранение).



NVT ASCII



NVT ASCII

Термин NVT ASCII означает 7-битный вариант U.S. ASCII набора символов, который используется в семействе протоколов Internet. Каждый 7-битный символ отправляется как 8-битный байт со старшим битом установленным в 0.

Конец строки передается как двухсимвольная последовательность - CR (возврат каретки - carriage return), затем следует LF (пропуск строки - linefeed). Мы показываем это как \r\n. Возврат каретки передается как двухсимвольная последовательность CR, за которой следует NUL (нулевой байт). Мы показываем это как \r\0.

В следующих главах мы увидим, что FTP, SMTP, Finger и Whois используют NVT ASCII для ввода команд клиента и откликов сервера.



NVT ASCII

Одна из характеристик SMTP заключается в том, что он использует NVT ASCII абсолютно везде: в конверте, заголовке и теле сообщения. Как мы сказали в разделе "Протокол Telnet" главы 26, NVT ASCII это 7-битная кодировка символов, символы при этом передаются как 8-битные байты, у которых старший бит установлен в 0.



Обмен пакетами и расчет RTT



Рисунок 21.2 Обмен пакетами и расчет RTT.


Также обратите внимание на то, что на этом рисунке мы пронумеровали сегменты 1-13 и 15 в том порядке, в котором они были отправлены или приняты хостом slip. Это соответствует выводу tcpdump, который был получен для этого хоста.



Обмен пакетами в процессе повторной передачи в районе 10секундной метки



Рисунок 21.7 Обмен пакетами в процессе повторной передачи в районе 10-секундной метки.


Мы удалили все объявления окна, за исключением сегмента 72, который мы обсудим ниже. slip всегда объявляет окно равное 4096, а vangogh объявляет окно равное 8192. Сегменты на этом рисунке пронумерованы как продолжение рисунка 21.2, где первый сегмент данных по соединению был с номером 1. Как и на рисунке 21.2, сегменты пронумерованы в соответствии с тем, как они отправлялись или принимались на хосте slip, где была запущена программа tcpdump. Мы также удалили несколько сегментов, которые не имели отношения к нашему обсуждению (44, 47 и 49, а также все ACK от vangogh).

Случилось так, что сегмент 45 либо потерялся, либо пришел поврежденным - мы не можем сказать этого определенно, основываясь на выводе команды. Все что мы можем увидеть на хосте slip это то, что было подтверждено все, за исключением байта 6657 (сегмент 58), за которым следовали следующие восемь ACK с тем же самым номером последовательности. Прием сегмента 62, третьего из дублированных ACK, вызвал повторную передачу данных, начиная с номера последовательности 6657 (сегмент 63). В действительности, реализации, происходящие от Berkeley, подсчитывают количество принятых дублированных ACK, и когда принимается третий, они подразумевают, что сегмент потерян, и повторно передают только один сегмент, начиная с этого номера последовательности. Подобное поведение является частью алгоритма быстрой повторной передачи (fast retransmit), который следует за алгоритмом быстрого восстановления данных (fast recovery algorithm), которые мы обсудим в разделе "Быстрая повторная передача и алгоритм быстрого восстановления" этой главы.

Обратите внимание на то, что после повторной передачи (сегмент 63) отправитель продолжает обычную передачу данных (сегменты 67, 69 и 71). TCP не ожидает того, что удаленный конец подтвердит повторную передачу.

Давайте посмотрим, что происходит на принимающем конце. Когда обычные данные приходят последовательно (сегмент 43), принимающий TCP передает 256 байт данных пользовательскому процессу. Однако следующий принятый сегмент (сегмент 46) не в порядке; стартовый номер последовательности данных (6913) не является следующим ожидаемым номером последовательности (6657). TCP сохраняет 256 байт данных и отвечает посредством ACK с самый большим номером последовательности, который был принят успешно, плюс один (6657). Следующие семь сегментов, принятых vangogh (48, 50, 52, 54, 55, 57 и 59), также не в порядке. Данные сохраняются принимающим TCP, и генерируются дублированные ACK.

Таким образом, для TCP не существует способа сообщить удаленному концу, что сегмент отсутствует. Помимо этого TCP не может подтвердить поврежденные данные. Все что может сделать vangogh в подобном случае - это продолжать посылать ACK с номером 6657.

Когда прибывают отсутствующие данные (сегмент 63), принимающий TCP имеет в своем буфере байты данных 6657-8960. Он передает эти 2304 байта пользовательскому процессу. Все 2304 байта подтверждены в сегменте 72. Также обратите внимание на то, что этот ACK объявляет окно равное 5888 (8192 - 2304), так как пользовательский процесс не имеет возможности прочитать 2304 байта, которые уже готовы для него.

Если мы рассмотрим более подробно вывод команды tcpdump для моментов времени 14 и 21 на рисунке 21.6, то увидим, что они были вызваны получением трех дублированных ACK, а это указывает на то, что пакет был потерян. Во всех этих случаях только один пакет был передан повторно.

Мы продолжим рассмотрение этого примера в разделе "Пример переполнения (продолжение)" этой главы, после того как рассмотрим более подробно алгоритм предотвращения переполнения.



Обработка TCP полученной ICMP ошибки о недоступности хоста



Рисунок 21.12 Обработка TCP полученной ICMP ошибки о недоступности хоста.









Обсуждение опций



Обсуждение опций

Несмотря на то, что при начале работы Telnet подразумевается, что на каждом конце находится NVT, первый обмен данными, который происходит по Telnet соединению, являет собой обсуждение опций. Обсуждение опций это симметричный процесс - каждая сторона может послать запрос другой.

Каждая сторона может послать один из четырех различных запросов для любой заданной опции.

WILL. Отправитель хочет включить эту опцию для себя. DO. Отправитель хочет, чтобы получатель включил эту опцию. WONT. Отправитель хочет выключить эту опцию для себя. DONT. Отправитель хочет, чтобы получатель выключил опцию.

Так как правила Telnet позволяют стороне принять или отклонить запрос на включение опции (случаи 1 и 2), однако требуют, чтобы она всегда удовлетворяла запрос на выключение опции (случаи 3 и 4), из этих четырех возможных случаев может получиться шесть комбинаций, которые приведены на рисунке 26.9.

Отправитель Получатель Описание
1. WILL ®
¬

DO
отправитель хочет включить опцию
получатель говорит ДА
2. WILL ®
¬

DONT
отправитель хочет включить опцию
получатель говорит НЕТ
3. DO ®
¬

WILL
отправитель хочет, чтобы получатель включил опцию
получатель говорит ДА
4. DO ®
¬

WONT
отправитель хочет, чтобы получатель включил опцию
получатель говорит НЕТ
5. WONT ®
¬

DONT
отправитель хочет выключить опцию
получатель должен сказать ДА
6. DONT ®
¬

WONT
отправитель хочет, чтобы получатель выключил опцию
получатель должен сказать ДА


Обсуждение подопций



Обсуждение подопций

Некоторые опции требуют большего количества информации, нежели просто "включить" (enable) или "выключить" (disable). Например, установка типа терминала: для того чтобы клиент мог идентифицировать тип терминала, он должен отправить ASCII строку. Чтобы обработать эти опции, применяется обсуждение подопций.

RFC 1091 [VanBokkelen 1989] определяет подопции, которые необходимо обсудить для установки типа терминала. Во-первых, одна сторона (обычно клиент) просит включить опцию, отправляя 3-байтовую последовательность

<IAC, WILL, 24>

где 24 (десятичное) это идентификатор опции типа терминала. Если получатель (сервер) говорит ДА, его ответ будет выглядеть как

<IAC, DO, 24>

Затем сервер посылает

<IAC, SB, 24, 1, IAC, SE>

спрашивая о типе терминала клиента. SB это команда, которая сообщает о начале подопций (suboption-begin). Следующий байт равный 24 указывает на то, что это подопция типа терминала. (SB всегда следует за номером опции, к которой относятся подопции.) Следующий байт равный 1 означает "отправьте ваш тип терминала". Перед командой конец подопций (suboption-end) должен опять стоять IAC, так же как и перед командой SB. Клиент отвечает командой

<IAC, SB, 24, 0, 'I', 'B', 'M', 'P', 'C', IAC, SE>

в случае, если его тип терминала ibmpc. Четвертый байт равный 0 означает "у меня следующий тип терминала". ("Официальный" список приемлемых типов терминалов находится в Assigned Numbers RFC, однако для Unix систем приемлем любой тип терминала, поддерживаемый сервером. Обычно это терминалы, поддерживаемые базами termcap или terminfo.) Типы терминалов, указываемые в подопциях Telnet, пишутся большими буквами и обычно преобразуются в маленькие буквы уже сервером.



Опция масштабирования окна



Опция масштабирования окна

Опция масштабирования окна увеличивает определение окна TCP с 16 до 32 бит. Вместо того чтобы изменять TCP заголовок, для того чтобы поместить в него окно большего размера, заголовок все так же содержит 16-битное значение, а опция определяет операцию масштабирования этого 16-битного значения. После чего TCP использует "реальный" размер окна внутри себя как 32-битное значение.

Мы видели пример использования этой опции на рисунке 18.20. 1-байтовый сдвиговый счетчик находится в диапазоне от 0 (нет масштабирования) до 14. Максимальное значение равное 14 соответствует окну размером 1.073.725.440 байт (65535 x 214).

Эта опция может появиться только в сегменте SYN; таким образом, коэффициент масштабирования определяется в каждом направлении при установлении соединения. Чтобы включить масштабирование окна, оба конца должны активизировать опцию в своих сегментах SYN. Сторона, осуществляющая активное открытие, посылает опцию в своем SYN, однако сторона, осуществляющая пассивное открытие, может послать опцию, только если эта опция установлена в полученном SYN. Коэффициент масштабирования может быть различен для каждого направления.

Если сторона, осуществляющая активное открытие, устанавливает ненулевой коэффициент масштабирования, однако не получает опцию масштабирования окна с удаленного конца, эта сторона устанавливает свой сдвиговый счетчик отправки и приема в 0. Таким образом добиваются совместимости новых систем со старыми, не поддерживающими эту опцию.

Требования к хостам Host Requirements RFC требуют, чтобы TCP принимал эту опцию в любом сегменте. (Единственная заранее определенная опция, максимальный размер сегмента, может появиться только в сегментах SYN.) Также этот документ требует, чтобы TCP игнорировал любые опции, которые он не понимает. Это легко осуществимо, так как все новые опции имеют поле длины (рисунок 18.20).

Представьте, что мы используем опцию масштабирования окна со сдвиговым счетчиком равным S для отправки и со сдвиговым счетчиком равным R для приема. В этом случае каждые 16 бит объявленного окна, которые мы получаем от удаленного конца, сдвигаются влево на R бит, чтобы получить реальный размер объявленного окна. Каждый раз, когда мы отправляем объявление окна на удаленный конец, мы берем реальный 32-битный размер окна, сдвигаем его вправо на S бит, помещаем получившийся результат (16-битное значение) в TCP заголовок.

TCP автоматически выбирает значение сдвигового счетчика, основываясь на размере приемного буфера. Размер приемного буфера устанавливается системой, однако приложению дается возможность изменить его. (Мы обсудили приемный буфер в разделе "Размер окна" главы 20.)



Опция временной марки



Опция временной марки

Опция временной марки (timestamp) позволяет отправителю поместить значение временной марки в каждый сегмент. Получатель возвращает это значение в подтверждении, что позволяет отправителю рассчитать RTT при получении каждого ACK. (Мы должны сказать " каждый ACK", а не "каждый сегмент", так как TCP обычно подтверждает несколько сегментов с помощью одного ACK.) Мы сказали, что большинство современных реализаций рассчитывают одно RTT на окно, что вполне достаточно, если окно содержит 8 сегментов. Однако в случае, если окно имеет большие размеры, требуется лучший расчет RTT.

Раздел 3.1 в RFC 1323 объясняет причины, по которым требуется лучшая оценка RTT при больших размерах окна. Обычно RTT измеряется с помощью сигнала данных (сегмент данных), с небольшой частотой (один раз на окно). Когда в окне 8 сегментов, скорость сигналов составляет одну восьмую скорости данных, что вполне приемлемо, однако когда в окне 100 сегментов, скорость сигналов составляет 1/100 от скорости данных. При этом RTT может быть рассчитано некорректно, что, в свою очередь, может вызвать повторные передачи, в которых нет необходимости. Если сегмент потерян, все становится еще хуже.

На рисунке 18.20 показан формат опции временной марки. Отправитель помещает 32-битное значение в первое поле, а получатель отражает его эхом в поле отклика. TCP заголовки, содержащие эту опцию, увеличиваются с обычных 20 байт до 32-х.

Временная марка - монотонно увеличивающееся значение. Так как получатель отражает то, что он получает, его не интересуют конкретные значения временных марок. Эта опция не требует какой-либо формы синхронизации часов между двумя хостами. RFC 1323 рекомендует, чтобы значение временной марки увеличивалось на единицу в диапазоне от 1 миллисекунды до 1 секунды.

4.4BSD увеличивает временную марку каждые 500 миллисекунд, и эта временная марка сбрасывается в 0 при перезагрузке.

Обратитесь к рисунку 24.7. Разница временных марок между сегментом 1 и сегментом 11 составляет 89 промежутков размером по 500 миллисекунд. Что составляет 44,4 секунды.

Эта опция устанавливается при открытии соединения таким же образом, как и опция масштабирования окна, которую мы рассмотрели в предыдущем разделе. Сторона, осуществляющая активное открытие, устанавливает опцию в своем SYN. Только если опция получена в SYN с удаленного конца, она может быть установлена в следующих сегментах.

Мы видели, что получающий TCP не должен подтверждать каждый полученный сегмент данных. Если получатель отправляет ACK, подтверждающий два принятых сегмента данных, которая из принятых временных марок отправляются назад в поле эха отклика на временную марку?

Чтобы минимизировать количество состояний, обрабатываемых на каждом конце, только одно единственное значение временной марки используется для каждого соединения. Алгоритм, по которому выбирается момент, когда необходимо обновить это значение, довольно прост.

TCP всегда знает значение временной марки, которое необходимо послать в следующем ACK (переменная с именем tsrecent), и номер последовательности подтверждения последнего ACK, который был отправлен (переменная с именем lastack). Номер последовательности это следующий номер последовательности, который ожидает принять получатель. Когда прибывает сегмент, содержащий байт, номер которого хранится в lastack, значение временной марки из этого сегмента сохраняется в tsrecent. Когда бы ни была отправлена опция временной марки, tsrecent отправляется в поле эха отклика временной марки, а поле номера последовательности сохраняется в lastack.

Этот алгоритм обрабатывает два следующих случая: Если подтверждения (ACK) задержаны получателем, значение временной марки, возвращаемое эхом, будет соответствовать самому раннему подтверждаемому сегменту. Например, если прибыло два сегмента содержащие байты 1-1024 и 1025-2048, оба с опцией временной марки, а получатель подтверждает их обоих с ACK 2049, временная марка в ACK будет иметь значение из первого сегмента, содержащего байты 1-1024. Это делается именно так, потому что отправитель должен рассчитать свой тайм-аут для повторной передачи, с учетом задержанных ACK. Если полученный сегмент принят в своем окне, но его номер последовательности не соответствует ожидаемому, можно сделать предположение, что предыдущий сегмент был потерян. Однако когда этот отсутствующий сегмент получен, именно его временная марка будет отражена эхом, а не временная марка сегмента, пришедшего "вне очереди". Например, представьте себе три сегмента, каждый из которых содержит 1024 байта, они приняты в следующем порядке: сегмент 1 с байтами 1-1024, сегмент 3 с байтами 2049-3072 и затем сегмент 2 с байтами 1025-2048. Будут отправлены следующие подтверждения: ACK 1025 с временной маркой из сегмента 1 (обычный ACK для ожидаемых данных), ACK 1025 с временной маркой из сегмента 1 (дублированный ACK в ответ на сегмент, пришедший "в окне", но "вне последовательности") и затем ACK 3073 с временной маркой из сегмента 2 (но не с последней временной маркой из сегмента 3). В подобных случаях RTT может быть оценен несколько раз, что все же лучше чем неверная оценка RTT. Также, если последний ACK содержит временную марку из сегмента 3, он может включать в себя время, необходимое для возврата дублированного ACK и повторной передачи сегмента 2, или он может включать в себя время, выделенное отправителем на тайм-аут повторной передачи для сегмента 2. В обоих случаях отражение эхом временной марки из сегмента 3 может повлиять на расчет RTT отправителем.

Помимо того, что опция временной марки позволяет лучше рассчитывать RTT, она также предоставляет получателю способ избежать получения старых сегментов и воспринятия их как части существующих сегментов данных. Это описывается в следующем разделе.



Оператор getnext



Оператор get-next

Функционирование оператора get-next основано на лексикографическом порядке MIB. Мы начнем следующий пример с запроса следующего идентификатора объекта после udp (не указывая объект, так как это не листовой объект). При этом будет возвращен первый объект группы UDP. Затем мы запросим следующую запись, будет возвращена вторая запись. И наконец, мы повторим это еще раз, чтобы получить третью запись:

sun % snmpi -a gateway -c secret

snmpi> next udp
udpInDatagrams.0=616318

snmpi> next udpInDatagrams.0
udpNoPorts.0=33

snmpi> next udpNoPorts.0
udpInErrors.0=0

Этот пример показывает, почему оператор get-next должен возвращать имя переменной: мы спрашиваем агента о следующей переменной, и агент возвращает ее имя и значение.

При использовании оператора get-next менеджер осуществляет циклический опрос всех переменных, поддерживаемых агентом (цикл стартует с начала MIB). Другое использование этого оператора - просмотр таблиц.



В этом описании мы будем



Описание

В этом описании мы будем называть конец, на котором включается опция "оставайся в живых", сервером, а другой конец - клиентом. Ничто не запрещает клиенту установить эту опцию, однако она устанавливается именно на сервере. Опция может быть установлена на обоих концах соединения, если каждому концу необходимо знать, работает ли удаленный конец. (В главе 29 мы увидим, что когда NFS использует TCP, оба, и клиент, и сервер, устанавливают эту опцию. А в главе 26, когда мы будем рассматривать Rlogin и Telnet, мы увидим, что эту опцию устанавливает только сервер, но не клиент.)
Если в заданном соединении не осуществляются какие-либо действия в течение 2 часов, сервер отправляет клиенту пробный сегмент. (Мы увидим, что представляет из себя пробный сегмент, в примере, который приведен ниже.) Хост клиента должен находиться в одном из четырех состояний. Хост клиента включен и доступен для сервера. TCP клиент откликается нормально, и сервер знает, что удаленный конец все еще включен. TCP сервер перезапустит таймер "оставайся в живых" еще на 2 часа. Если до истечения следующих 2 часов по соединению будет осуществлен какой-либо обмен, таймер снова сбросится и установится в 2 часа. Хост клиента вышел из строя и либо выключен, либо перезагружается. В обоих случаях его TCP не отвечает. Сервер не получит отклик на свою пробу и отработает тайм-аут равный 75 секундам. Всего сервер отправляет 10 таких проб, с интервалом в 75 секунд, и если он так и не получил отклика, сервер считает, что хост клиента выключен, и разрывает соединение. Хост клиента вышел из строя и перезагрузился. В этом случае сервер получит отклик на свою пробу "оставайся в живых", однако отклик будет игнорирован и сервер разорвет соединение. Хост клиента запущен и работает, однако недоступен для сервера. Для TCP это то же самое, что и пункт 2. В обоих случаях можно сказать, что на пробы не получен отклик.
Сервер не должен беспокоиться о том, что хост клиента был выключен и затем перезагружен. (Имеется ввиду shutdown, а не выход хоста из строя.) Когда система выключена оператором, все процессы клиента корректно завершают свою работу, при этом TCP клиент отправляет FIN для соединения. При получении FIN, TCP сервер выдает метку конца файла процессу сервера, что позволяет серверу корректно закрыть соединение.
В первом сценарии приложение сервера не подозревает о том, что были отправлены пробы "оставайся в живых". Все это делается на TCP уровне. Для приложения абсолютно безразлично, имели ли место сценарии 2, 3 или 4. Во всех трех случаях приложению сервера возвращается ошибка от его собственного TCP. (Обычно сервер осуществляет чтение из сети, ожидая данные от клиента. Если характеристика "оставайся в живых" возвратила ошибку, она передается серверу как код возврата на операцию чтения.) В случае второго сценария ошибка выглядит примерно следующим образом: "соединение закрыто по тайм-ауту" (connection timed out), а в случае третьего сценария мы можем ожидать "соединение сброшено удаленным концом" (connection reset by peer). Четвертый сценарий может выглядеть как, если соединение разорвано по тайм-ауту, однако может быть возвращена и другая ошибка, в зависимости от того, какая принята ICMP ошибка по этому соединению. Мы рассмотрим все четыре сценария в следующих разделах.
Вечный вопрос, который задают люди, изучающие опцию "оставайся в живых", заключается в том, может ли быть изменено значение 2-часового тайм-аута. Обычно требуется значительно меньше времени, где-то несколько минут. Как мы показали в приложении Е, это значение обычно может быть изменено, однако во всех системах, описанных в этом приложении, интервал "оставайся в живых" является системным значением, поэтому его изменение окажет влияние на всех пользователей.
Требования к хостам Host Requirements RFC говорят, что реализации могут иметь характеристику "оставайся в живых", однако она не должна включаться, за исключением тех случаев, когда приложение специально требует это. Более того, интервал "оставайся в живых" должен быть конфигурируемым, однако по умолчанию он должен быть не меньше чем 2 часа.



Описание работы Telnet клиентсервер



Рисунок 26.2 Сравнение размеров исходных текстов Telnet/Rlogin/клиент/сервер.


Надо отметить, что из-за появления новых опций, реализация Telnet постоянно растет, тогда как Rlogin остается простым и стабильным.

При заходе удаленным терминалом не предусматривается передача большого количества данных. Как мы уже упоминали ранее, по соединению между двумя конечными системами обычно передается очень много маленьких пакетов. В соответствии с [Paxson 1993] соотношение байт, отправленных клиентам (пользовательский ввод с терминала), к количеству байт, отправленных назад серверам, составляет примерно 1:20. Такое соотношение получается из-за того, что мы вводим короткие команды, которые, в свою очередь, могут генерировать очень большой вывод.

Протокол Rlogin

Rlogin появился в 4.2BSD и был предназначен для захода удаленным терминалом между Unix хостами. Поэтому Rlogin проще, чем Telnet, так как он не требует определение параметров, которые для одной и той же операционной системы известны заранее и для клиента, и для сервера. Через несколько лет Rlogin был перенесен на не-Unix системы.

RFC 1282 [Kantor 1991] содержит спецификацию протокола Rlogin. Однако, как и в случае с RFC посвященным RIP (Routing Information Protocol), он был написан после того, как Rlogin уже использовался в течении нескольких лет. Глава 15 [Stevens 1990] описывает программирование клиента и сервера удаленного терминала и предоставляет полные исходные тексты Rlogin клиента и сервера. Главы 25 и 26 [Comer and Stevens 1993] сдержат подробности разработки и исходные тексты Telnet клиента.



Описатели файлов



Описатели файлов

Одна из основ NFS реализуется описателями файлов. Для обращения к файлу или директории на сервере объекта используется opaque. Термин opaque обозначает, что сервер создает описатель файла, передает его обратно клиенту, который клиент затем использует при обращении к файлу. Клиент никогда не просматривает содержимое описателя файла - его содержимое представляет интерес только для сервера.

NFS клиент получает описатель файла каждый раз когда открывает файл, который в действительности находится на NFS сервере. Когда NFS клиент читает или пишет в этот файл (по поручению пользовательского процесса), описатель файла передается обратно серверу. Это указывает на то, что доступ к файлу был осуществлен.

Обычно пользовательский процесс не работает с описателями файлов. Обмен описателями файлов осуществляют NFS клиент и NFS сервер. В версии 2 NFS описатель файла занимает 32 байта, а в версии 3 он вырос до 64 байт.

Unix серверы обычно хранят в описателе файла следующую информацию: идентификатор файловой системы (major и minor номера устройства файловой системы), номер инода (i-node) (уникальный номер внутри файловой системы), номер поколения инода (номер, который изменяется каждый раз, когда инод повторно используется для другого файла).



Определение транспортного MTU



Определение транспортного MTU

В разделе "Транспортный MTU" главы 2 мы описали концепцию транспортного MTU (path MTU). Это минимальный MTU в любой из сетей, по которым проходит маршрут между двумя хостами. При определении транспортного MTU в IP заголовке устанавливается бит "не фрагментировать" (DF - don't fragment), что позволяет определить, необходимо ли какому-либо маршрутизатору на текущем маршруте фрагментировать IP датаграммы, которые мы посылаем. В разделе "ICMP ошибки о недоступности" главы 11 мы показали ICMP ошибку о недоступности, генерируемую маршрутизатором, которому необходимо перенаправить IP датаграмму с установленным битом DF, когда MTU меньше чем размер датаграммы. В разделе "Определение транспортного MTU с использованием Traceroute" главы 11 мы показали версию программы traceroute, которая использует этот механизм, чтобы определить транспортный MTU к пункту назначения. В разделе "Определение транспортного MTU при использовании UDP" главы 11 мы видели, как UDP определял транспортный MTU. В этом разделе мы просмотрим, как TCP использует этот механизм. Это описано в RFC 1191 [Mogul and Deering 1990].

Из всех систем, которые используются в этой книге (см. вступление), только Solaris 2.x поддерживает определение транспортного MTU.

Алгоритм определения транспортного MTU TCP работает следующим образом. Когда соединение установлено, TCP использует минимальный MTU исходящего интерфейса или MSS, объявленный удаленным концом, в качестве исходного размера сегмента. Алгоритм определения транспортного MTU не позволяет TCP превосходить MSS, объявленный удаленным концом. Если удаленный конец не указал MSS, то он устанавливается по умолчанию в значение равное 536. Реализации могут сохранить информацию о транспортном MTU определенного канала, как мы говорили в разделе "Показатели на маршрут" главы 21.

После того как выбран исходный размер сегмента, во всех IP датаграммах, отправляемых TCP по этому соединению, установливается бит DF. Если промежуточному маршрутизатору необходимо фрагментировать датаграмму, в которой установлен бит DF, он отбрасывает датаграмму и генерирует ICMP ошибку "не могу фрагментировать" (can't fragment). Это описано в разделе "ICMP ошибки о недоступности" главы 11. Если принята такая ICMP ошибка, TCP уменьшает размер сегмента и повторяет передачу. Если маршрутизатор сгенерировал новую ICMP ошибку, размер сегмента может быть установлен в MTU следующей пересылки минус размеры IP и TCP заголовков.

Если возвратилась старая ICMP ошибка, должно быть использовано следующее меньшее значение MTU (рисунок 2.5). Когда осуществляются повторные передачи, вызванные этими ICMP ошибками, окно переполнения не должно изменяться, вместо этого должен быть использован медленный старт.

Так как маршруты могут меняться со временем, по истечении определенного времени после последнего уменьшения транспортного MTU, можно попробовать большее значение (до величины минимального MSS, объявленного удаленным концом, или MTU исходящего интерфейса). RFC 1191 рекомендует, чтобы этот временной интервал составлял примерно 10 минут. (Мы видели в разделе "Определение транспортного MTU при использовании UDP" главы 11, что Solaris 2.2 использует для этих целей 30-секундный тайм-аут.)

Используя обычное для работы в глобальных сетях значение MSS по умолчанию равное 536, алгоритм определения транспортного MTU избегает фрагментации по промежуточным каналам с MTU меньшим чем 576 (что встречается довольно редко). Также можно избежать фрагментации в локальных сетях, когда промежуточный канал (Ethernet) имеет меньший MTU, чем сеть конечного пункта назначения (Token ring). В процессе определения транспортного MTU (при работе в глобальных сетях с MTU большим чем 576), системы не должны использовать MSS по умолчанию равный 536 байт для нелокальных пунктов назначения. Предпочтительней выбирать MSS равный MTU исходящего интерфейса (естественно, минус размер IP и TCP заголовков). (В приложении Е мы увидим, что большинство реализаций позволяют системным администраторам изменить значение MSS принятое по умолчанию.)



Определение времени возврата



Определение времени возврата

Основой тайм-аутов и повторных передач TCP является расчет времени возврата (RTT - round-trip time), соответствующего данному соединению. Мы ожидаем, что оно может изменяться со временем, так как может измениться маршрут, или загрузка сети. TCP должен отследить эти изменения и соответственно модифицировать тайм-ауты.

Во-первых, TCP должен рассчитать RTT между отправкой байта с конкретным номером последовательности и получением подтверждения на этот номер последовательности. Из предыдущей главы мы знаем, что обычно не существует полного соответствия между сегментами данных и подтверждениями (ACK). На рисунке 20.1 это означало, что один RTT, который может быть вычислен отправителем, является временем между передачей сегмента 4 (байты данных 1-1024) и получением сегмента 7 (ACK байт 1-2048), даже если этот ACK подтверждает дополнительно 1024 байта. Мы используем величину M, чтобы обозначить рассчитанный RTT.

Для определения RTT существует расширение к исходной спецификации TCP, которое называется хэшированная оценочная функция RTT (обозначается R)

R ¬ a R + (1 - a )M

где a это коэффициент хэширования с рекомендуемым значением 0,9. Хэширование - способ организации структур данных (хэш таблиц), обеспечивающий эффективный поиск и пополнение; положение элемента данных в хэш таблице определяется значением функции расстановки, отображающей множество возможных ключей элементов данных и множество индексов таблицы и обеспечивающей равномерное заполнение. Хэшированный RTT обновлялся каждый раз, когда осуществлялось новое вычисление. Девяносто процентов данных для каждого нового расчета берется из предыдущего расчета, а десять из нового.

Для подобной хэшированной оценочной функции, которая изменяется с изменением RTT, RFC 793 рекомендует, чтобы тайм-аут повторной передачи (RTO) устанавливался следующим образом

RTO = Rb

где b это коэффициент изменения задержки с рекомендуемым значением равным 2.

[Jacobson 1988] подробно обсуждает проблемы, связанные с подобным подходом, в основном заключающиеся в том, что он не может применяться при широком диапазоне изменения RTT, и является причиной нежелательных повторных передач. Как замечает Jacobson, нежелательные повторные передачи увеличивают загрузку сети.

В этом случае необходимо добавить возможность отслеживать расхождения в расчетах RTT в дополнение к хэшированной функции оценки RTT. Расчет RTO основанный на среднем и расхождении дает значительно лучшие результаты при широком диапазоне изменений времен возврата, чем просто расчет RTO как постоянного кратного среднего значения. Рисунки 5 и 6 в [Jacobson 1988] показывают сравнение значений RTO в соответствии с RFC 793 для некоторых реальных времен возврата, с расчетами RTO, которые мы показали ранее, которые принимают во внимание изменение времен возврата.

Как описано у Jacobson, среднее отклонение является хорошим приближением к стандартному отклонению, однако рассчитывается значительно легче. (Расчет стандартного отклонения требует вычисления квадратного корня.) Таким образом, следующие уравнения могут быть применены к каждому расчету RTT M.

Err = M - A

A ¬ A + gErr

D ¬ D + h(| Err | - D)

RTO = A + 4D

где A это хэшированный RTT (оценочная функция среднего), а D это хэшированное среднее отклонение. Err это разница между только что рассчитанным значением и текущим значением оценочной функции RTT. Оба A и D используются для расчета следующего тайм-аута повторной передачи (RTO). Увеличение среднего (g) установлено в значение 1/8 (0,125). Увеличение отклонения (h) установлено в 0,25. Максимальное увеличение отклонения делает рост RTO быстрее при изменении RTT.

[Jacobson 1988] устанавливает 2D при расчете RTO, однако для следующих исследований [Jacobson 1990c] изменяет это значение на 4D, что соответствует реализации BSD Net/1.

Jacobson показывает способ осуществить эти вычисления с использованием целочисленной арифметики, именно так это обычно делается в стандартных реализациях. (Одна из причин заключается в том, что g, h и множитель 4 - это степени двух, поэтому все операции могут быть осуществлены с помощью сдвига, без умножений и делений.)

Сравнение исходного метода с методом Jacobsonа показывает, что расчеты хэшированного среднего одинаковы (a равно единица минус увеличение (g)), однако используются различные увеличения. Также, расчет RTO по Jacobsonу зависит от обоих значений - хэшированного RTT и хэшированного среднего отклонения, тогда как оригинальный метод использует умножение хэшированных RTT.

В следующем разделе мы увидим, как устанавливаются эти оценочные функции, когда будем рассматривать примеры.



Определение времени возврата

Три большие фигурные скобки, находящиеся с левой стороны временной диаграммы, указывают на то, какие сегменты были использованы при расчете RTT. Не для всех сегментов время было засечено.

Большинство реализаций TCP, происходящих от Berkeley, рассчитывают только одно значение RTT для соединения за один раз. Если в тот момент, когда отправляется сегмент данных, таймер для данного соединения уже используется, время для этого сегмента не засекается.

Установка времени осуществляется путем увеличения счетчика каждый раз, когда запускается 500-миллисекундный таймер TCP. Это означает, что для сегмента, подтверждение на который прибывают через 550 миллисекунд после того, как сегмент был отправлен, может быть принято RTT как равное одному тику (500 миллисекунд), так и RTT равное двум тикам (1000 миллисекунд).

В дополнение к этому счетчику тиков для каждого соединения, запоминается начальный номер последовательности данных в сегменте. Когда принимается подтверждение, содержащее этот номер последовательности, таймер выключается. Если данные не были повторно переданы, когда прибыл ACK, хэшированное RTT и хэшированное среднее отклонение обновляется на основе новых значений.

Таймер для соединения, показанного на рисунке 21.2, стартует, когда передается сегмент 1, и выключается, когда прибывает подтверждение на него (сегмент 2). Несмотря на то, что его RTT равен 1,061 секунды (из вывода команды tcpdump), исследование отладочной информации сокета показывает, что за этот период произошло 3 тика часов TCP, а это обозначает, что RTT равен 1500 миллисекунд.

Следующий сегмент, для которого засекли время, сегмент номер 3. Когда, через 2,4 миллисекунды, передается сегмент номер 4, он не может быть отслежен по времени, так как таймер для этого соединения уже используется. Когда прибывает сегмент 5, подтверждая данные, на которые было засечено время, его RTT рассчитывается равным 1 тику (500 миллисекунд), даже несмотря на то, что, как мы видели из вывода команды tcpdump, его RTT равен 0,808 секунды.

Таймер стартует снова, когда передается сегмент 6, и выключается, когда прибывает подтверждение на него, через 1,015 секунды (сегмент 10). Полученный RTT равен 2 тикам часов. Сегменты 7 и 9 не могут быть оценены по времени, так как таймер занят. Также, когда принимается сегмент 9 (ACK 769), ничего не обновляется, так как подтверждение не подтверждает байты, на которые засекли время.

На рисунке 21.3 показана взаимосвязь между реальными RTT, которые мы можем определить из вывода команды tcpdump, и счетчиком тиков часов.