• 10.1 Введение
  • 10.1.1 Основные службы TCP
  • 10.1.2 TCP и модель клиент/сервер
  • 10.2 Концепции TCP
  • 10.2.1 Входной и выходной потоки данных
  • 10.2.2 Сегменты
  • 10.2.3 Выталкивание
  • 10.2.4 Срочные данные
  • 10.2.5 Порты приложения
  • 10.2.6 Адреса socket
  • 10.3 Механизм обеспечения надежности TCP
  • 10.3.1 Нумерация и подтверждение
  • 10.3.2 Поля портов, последовательности и ACK в заголовке TCP
  • 10.4 Установка соединения
  • 10.4.1 Сценарий соединения
  • 10.4.2 Установка значений параметров IP
  • 10.5 Пересылка данных
  • 10.6 Закрытие соединения
  • 10.6.1 Внезапное завершение
  • 10.7 Управление потоком
  • 10.7.1 Приемное окно
  • 10.7.2 Окно отправки
  • 10.8 Заголовок TCP
  • 10.8.1 Вариант максимального размера сегмента
  • 10.8.2 Использование полей заголовка в запросе на соединение
  • 10.8.3 Использование полей заголовка в ответе на запрос соединения
  • 10.8.4 Выбор начального порядкового номера
  • 10.8.5 Общепринятое использование полей
  • 10.8.6 Контрольная сумма
  • 10.9 Пример сегмента TCP
  • 10.10 Поддержка работы сеанса
  • 10.10.1 Зондирование окна
  • 10.11 Завершение сеанса
  • 10.11.1 Тайм-аут
  • 10.11.2 Поддержание соединения
  • 10.12 Производительность
  • 10.13 Алгоритмы повышения производительности
  • 10.13.1 Медленный старт
  • 10.13.2 Синдром "бестолкового окна"
  • 10.13.3 Алгоритм Нейгла
  • 10.13.4 Задержанный ACK
  • 10.13.5 Тайм-аут повторной пересылки
  • 10.13.6 Пример статистики
  • 10.13.7 Вычисления после повторной отправки
  • 10.13.8 Действия после повторной пересылки
  • 10.13.9 Экспоненциальное торможение
  • 10.13.10 Снижение перегрузок за счет уменьшения пересылаемых по сети данных
  • 10.13.11 Дублированные ACK
  • 10.13.12 Что делается после подавления источника?
  • 10.13.13 Статистика TCP
  • 10.14 Соответствие требованиям разработчика
  • 10.15 Барьеры для производительности
  • 10.16 Функции TCP
  • 10.17 Состояния TCP
  • 10.17.1 Анализ состояний соединения TCP
  • 10.18 Замечания о реализациях
  • 10.19 Дополнительная литература
  • Глава 10

    Протокол TCP

    10.1 Введение

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

    10.1.1 Основные службы TCP

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

    IP пытается доставлять датаграммы, прилагая максимальные усилия, однако по пути следования данные могут разрушиться или прибыть в точку назначения в ином порядке, чем были отправлены. Датаграмма может путешествовать по сети достаточно долго и прибывать в произвольные моменты времени. Именно в TCP обеспечивается надежность, порядок следования и исключаются неисправности и ошибки.

    Приложение быстрого и мощного хоста может перегрузить данными медленного получателя. В TCP реализовано управление потоком (flow control), позволяющее получателю (receiver) регулировать скорость пересылки данных отправителем. Кроме того, в TCP встроен механизм реакции на текущее состояние сети, подстраивающий поведение протокола для получения оптимальной производительности.

    10.1.2 TCP и модель клиент/сервер

    TCP естественным образом интегрируется в окружение клиент/сервер (см. рис. 10.1). Серверное приложение прослушивает (listen) поступающие запросы на соединение. Например, службы WWW, пересылки файлов или доступа с терминала прослушивают запросы, поступающие от клиентов. Коммуникации в TCP запускаются соответствующими подпрограммами, которые и инициализируют соединение с сервером (см. главу 21 о программном интерфейсе socket).

    Рис. 10.1. Клиент вызывает сервер.

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

    10.2 Концепции TCP

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

    10.2.1 Входной и выходной потоки данных

    Концептуальная модель соединения предполагает пересылку приложением потока данных равному приложению. В то же время оно способно принимать поток данных от своего партнера по соединению. TCP предоставляет полнодуплексный (full duplex) режим работы, при котором одновременно обслуживаются два потока данных (см. рис. 10.2).

    Рис. 10.2. Приложения обмениваются потоками данных.

    10.2.2 Сегменты

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

    Приложение передает данные в TCP, а этот протокол помещает их в выходной буфер (send buffer). Далее TCP вырезает куски данных из буфера и отправляет их, добавляя заголовок (при этом формируются сегменты — segment). На рис. 10.3 показано, как данные из выходного буфера TCP пакетируются в сегменты. TCP передает сегмент в IP для доставки в виде отдельной датаграммы. Пакетирование данных в куски правильной длины обеспечивает эффективность их пересылки, поэтому до создания сегмента TCP будет ожидать, пока в выходном буфере не появится соответствующее количество данных.

    Рис. 10.3 Создание сегмента TCP

    10.2.3 Выталкивание

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

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

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

    10.2.4 Срочные данные

    Модель пересылки данных приложением предполагает применение упорядоченного потока байтов, следующего к точке назначения. Снова обратившись к примеру интерактивного сеанса, предположим, что пользователь нажал клавишу attention (внимание) или break (прерывание). Удаленное приложение должно быть способно пропустить мешающие байты и отреагировать на нажатие клавиши как можно скорее.

    Механизм срочных данных (urgent data) маркирует специальную информацию в сегменте как срочную. Этим TCP сообщает своему партнеру, что сегмент содержит срочные данные, и может указать, где они находятся. Партнер должен переслать эту информацию в приложение назначения как можно скорее.

    10.2.5 Порты приложения

    Клиент должен идентифицировать службу, к которой он хочет получить доступ. Это выполняется через спецификацию IP-адреса службы хоста и его номера порта TCP. Как и для UDP, номера портов TCP находятся в диапазоне от 0 до 65 535. Порты в диапазоне от 0 до 1023 называются общеизвестными (well-known) и используются для доступа к стандартным службам.

    Несколько примеров общеизвестных портов и соответствующих им приложений показано в таблице 10.1. Службы Discard (порт 9) и chargen (порт 19) являются TCP-версиями уже известных нам по UDP служб. Нужно помнить, что трафик на порт 9 протокола TCP полностью изолирован от трафика на порт 9 протокола UDP.


    Таблица 10.1 Общеизвестные порты TCP и соответствующие им приложения

    Порт Приложение Описание
    9 Discard Отмена всех входящих данных
    19 Chargen Генератор символов. Обмен потоком символов
    20 FTP-Data Порт пересылки данных FTP
    21 FTP Порт для диалога FTP
    23 TELNET Порт для удаленной регистрации по Telnet
    25 SMTP Порт протокола SMTP
    110 POP3 Служба выборки почтовых сообщений для персональных компьютеров
    119 NNTP Доступ к сетевым новостям

    Что можно сказать о портах, используемых клиентами? В редких случаях клиент работает не через общеизвестный порт. Но в таких ситуациях, желая открыть соединение, он часто запрашивает у операционной системы присвоения ему неиспользуемого и незарезервированного порта. В конце соединения клиент обязан возвратить этот порт обратно, после чего порт может быть использован повторно другим клиентом. Поскольку в пуле нерезервированных номеров существует более 63 000 портов TCP, ограничения на порты для клиентов можно не учитывать.

    10.2.6 Адреса socket

    Как мы уже знаем, комбинация IP-адреса и порта для коммуникации называется адресом socket. Соединение TCP полностью идентифицируется адресом socket на каждом конце данного соединения. На рис. 10.4 показано соединение между клиентом с адресом socket (128.36.1.24, порт = 3358) и сервером с адресом socket (130.42.88.22, порт = 21).

    Рис. 10.4. Адреса socket

    Заголовок каждой датаграммы содержит IP-адреса источника и назначения. В дальнейшем будет видно, что номера портов источника и назначения указываются в заголовке сегмента TCP.

    Обычно сервер способен одновременно управлять несколькими клиентами. Уникальные адреса socket сервера присваиваются одновременно всем его клиентам (см. рис. 10.5).

    Рис. 10.5. Несколько клиентов соединены с адресами socket сервера

    Поскольку датаграмма содержит сегмент соединения TCP, идентифицирующийся IP-адресами и портами, серверу очень просто отслеживать несколько соединений с клиентами.

    10.3 Механизм обеспечения надежности TCP

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

    10.3.1 Нумерация и подтверждение

    Для обеспечения надежной пересылки данных в TCP используются нумерация (numbering) и подтверждение (acknowledgment — ACK). Схема нумерации TCP несколько необычна: каждый пересылаемый по соединению октет рассматривается как имеющий порядковый номер. Заголовок сегмента TCP содержит порядковый номер первого октета данных этого сегмента.

    От приемника требуется подтверждение получения данных. Если ACK не приходит за интервал тайм-аута, данные передаются повторно. Этот способ называется позитивным подтверждением с ретрансляцией (positive acknowledgment with retransmission).

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

    На рис. 10.6 показан упрощенный взгляд на тайм-аут и повторную пересылку в TCP.

    Рис. 10.6. Тайм-аут и повторная пересылка в TCP

    10.3.2 Поля портов, последовательности и ACK в заголовке TCP

    Как показано на рис. 10.7, первые несколько полей заголовка TCP предоставляют место для значений портов источника и назначения, порядкового номера первого байта вложенных данных и ACK, равного порядковому номеру следующего байта, ожидаемого на другом конце. Другими словами, если TCP от своего партнера получит все байты до 30-го, в этом поле будет значение 31, указывающее сегмент, который следует переслать далее.

    Рис. 10.7. Начальные значения в полях заголовка TCP

    Нельзя не отметить одну маленькую деталь. Предположим, что TCP переслал байты от 1 до 50 и более уже нет данных для отправки. Если от партнера поступают данные, TCP обязан подтвердить их получение, для чего пошлет заголовок без подключенных к нему данных. Естественно, в этом заголовке присутствует значение ACK. В поле последовательности — значение 51, т.е. номер следующего байта, который намеревается послать TCP. Когда TCP пошлёт следующие данные, новый заголовок TCP также будет иметь в поле последовательности значение 51.

    10.4 Установка соединения

    Каким образом два приложения соединяются между собой? Перед коммуникацией каждое из них вызывает подпрограмму для формирования блока памяти, который будет использован для хранения параметров TCP и IP данного соединения, например адресов socket, текущего порядкового номера, начального значения времени жизни и т.д.

    Серверное приложение ожидает появления клиента, который, желая получить доступ к серверу, выдает запрос на соединение (connect), идентифицирующий IP-адрес и порт сервера.

    Существует одна техническая особенность. Каждая сторона начинает нумерацию каждого байта не с единицы, а со случайного порядкового номера (далее мы узнаем, для чего это делается). Исходная спецификация дает совет: начальный порядковый номер генерировать на основе 32-разрядного внешнего таймера, увеличивающего значения примерно каждые 4 мкс.

    10.4.1 Сценарий соединения

    Процедуру соединения часто называют тройным рукопожатием (three-way handshake), поскольку для установки соединения производится обмен тремя сообщениями — SYN, SYN и ACK.

    Во время установки соединения партнеры обмениваются тремя важными порциями информации:

    1. Объем буферного пространства для приема данных

    2. Максимальное количество данных, переносимое во входящем сегменте

    3. Начальный порядковый номер, используемый для исходящих данных

    Отметим, что каждая из сторон применяет операции 1 и 2 для указания пределов, в которых будет действовать другая сторона. Персональный компьютер может иметь небольшой приемный буфер, а суперкомпьютер — огромный буфер. Структура памяти персонального компьютера может ограничивать поступающие порции данных 1 Кбайт, а суперкомпьютер управляется с большими сегментами.

    Способность управлять тем, как посылает данные другая сторона, является важным свойством, обеспечивающим масштабируемость TCP/IP.

    На рис. 10.8 показан пример сценария соединения. Представлены очень простые начальные порядковые номера, чтобы не перегружать рисунок. Отметим, что на данном рисунке клиент способен получать большие по размеру сегменты, чем сервер.

    Рис. 10.8. Установление соединения

    Выполняются следующие операции:

    1. Сервер инициализируется и становится готовым к соединению с клиентами (это состояние называется пассивным открытием — passive open).

    2. Клиент запрашивает у TCP открытие соединения с сервером по указанному IP-адресу и порту (это состояние называется активным открытием — active open).

    3. Клиентская TCP получает начальный порядковый номер (в данном примере — 1000) и посылает сегмент синхронизации (synchronize segment — SYN). В этом сегменте пересылается порядковый номер, размер приемного окна (4 К) и размер наибольшего сегмента, который может принять клиент (1460 байт).

    4. Когда поступает SYN, серверная TCP получает свой начальный порядковый номер (3000). Она посылает сегмент SYN, содержащий начальный порядковый номер (3000), ACK 1001 (что означает нумерацию первого посланного клиентом байта как 1001), размер приемного окна (4 К) и размер наибольшего сегмента, который сможет получить сервер (1024 байта).

    5. Клиентская TCP, получив от сервера сообщение SYN/ACK, отсылает обратно ACK 3001 (первый байт посланных сервером данных должен нумероваться как 3001).

    6. Клиентская TCP указывает своему приложению на открытие соединения.

    7. Серверная TCP, получив от клиентской TCP сообщение ACK, информирует свое приложение об открытии соединения.

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

    10.4.2 Установка значений параметров IP

    Запрос приложения на установку соединения может заодно указать параметры для датаграмм IP, которые будут переносить данные этого соединения. Если не указывается определенное значение параметра, используется величина, заданная по умолчанию.

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

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

    10.5 Пересылка данных

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

    Рис. 10.9. Простой поток обмене данными и ACK

    Первый посланный клиентом сегмент содержит байты от 1001 до 2000. В его поле ACK должно находиться значение 3001, что указывает порядковый номер байта, который предполагается получить от сервера.

    Сервер отвечает клиенту сегментом, содержащим 1000 байт данных (начинающихся с номера 3001). В его поле ACK заголовка TCP будет указано, что байты с 1001 по 2000 уже успешно получены, поэтому следующий ожидающийся от клиента порядковый номер сегмента должен быть 2001.

    Далее клиент посылает сегменты, начинающиеся с байтов 2001, 3001 и 4001 в указанной последовательности. Отметим, что клиент не ожидает ACK после каждого из посланных сегментов. Данные пересылаются партнеру до заполнения его буферного пространства (ниже мы увидим, что получатель может очень точно указать объем пересылаемых ему данных).

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

    На рис. 10.10 показана пересылка данных при потере первого сегмента. По завершении тайм-аута пересылка сегмента повторяется. Отметим, что, получив потерянный сегмент, приемник отправляет один ACK, подтверждающий пересылку обоих сегментов.

    Рис. 10.10. Потеря данных и повторная трансляция

    10.6 Закрытие соединения

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

    A: "Я закончил работу. Данных для пересылки больше нет".

    B: "Хорошо".

    В: "Я тоже завершил работу".

    A: "Хорошо".

    Допустим и такой сценарий (хотя он используется крайне редко):

    A: "Я закончил работу. Данных для пересылки больше нет".

    В: "Хорошо. Однако есть какие-то данные…"

    В: "Я тоже завершил работу".

    A: "Хорошо".

    В рассмотренном ниже примере соединение закрывает сервер, как это часто происходит для связей клиент/сервер. В данном случае после ввода пользователем в сеансе telnet команды logout (выйти из системы) сервер инициирует запрос на закрытие соединения. В ситуации, показанной на рис. 10.11, выполняются следующие действия:

    1. Приложение на сервере указывает TCP на закрытие соединения.

    2. TCP сервера посылает заключительный сегмент (Final Segment — FIN), информируя своего партнера о том, что данных для отправки больше нет.

    3. TCP клиента посылает ACK в сегменте FIN.

    4. TCP клиента сообщает своему приложению, что сервер хочет закрыть соединение.

    5. Клиентское приложение сообщает своему TCP о закрытии соединения.

    6. TCP клиента посылает сообщение FIN.

    7. TCP сервера получает FIN от клиента и отвечает на него сообщением ACK.

    8. TCP сервера указывает своему приложению на закрытие соединения.

    Рис. 10.11. Закрытие соединения

    Обе стороны могут одновременно начать закрытие. В этом случае обычное закрытие соединения завершается после отправки каждым из партнеров сообщения ACK.

    10.6.1 Внезапное завершение

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

    10.7 Управление потоком

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

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

    Поток данных поступает во входной буфер и сохраняется в нем до пересылки в приложение (определяемое портом TCP). На рис. 10.12 показан входной буфер, способный принять 4 Кбайт.

    Рис. 10.12. Приемное окно входного буфера

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

    10.7.1 Приемное окно

    Приемное окно (receive window) — любое пространство во входном буфере, еще не занятое данными. Данные остаются во входном буфере, пока не будут задействованы целевым приложением. Почему приложение не забирает данные сразу?

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

    Приемное окно расширяется от последнего подтвержденного байта до конца буфера. На рис. 10.12 сначала доступен весь буфер и, следовательно, доступно приемное окно в 4 Кбайт. Когда поступит первый Кбайт, приемное окно сократится до 3 Кбайт (для простоты мы будем считать, что каждый сегмент имеет размер в 1 Кбайт, хотя на практике это значение меняется в зависимости от потребностей приложения). Поступление следующих двух сегментов по 1 Кбайту приведет к сокращению приемного окна до 1 Кбайта.

    Далее приложение примет 3 Кбайт данных из буфера, освобождая место для приема следующей информации. Мысленно это можно представить как сдвиг окна влево. А в буфере доступными станут уже 4 Кбайт.

    Каждый посланный приемником ACK содержит сведения о текущем состоянии приемного окна, в зависимости от которого регулируется поток данных от источника.

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

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

    10.7.2 Окно отправки

    Система, передающая данные, должна отслеживать две характеристики: сколько данных уже было отправлено и подтверждено, а также текущий размер приемного окна получателя. Активное пространство отправки (send space) расширяется от первого неподтвержденного октета к левому краю текущего приемного окна. Часть окна, используемая для отправки, указывает, сколько еще дополнительных данных можно послать партнеру.

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

    1. Отправитель начинает работу с окном отправки в 4 Кбайт.

    2. Отправитель пересылает 1 Кбайт. Копия этих данных сохраняется до получения подтверждения (ACK), поскольку может потребоваться их повторная передача.

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

    4. Наконец поступает ACK для всех переданных данных (т.е. все они получены приемником). ACK восстанавливает размер окна отправки в 4 Кбайт.

    Рис. 10.13. Окно отправки

    Следует указать на несколько интересных особенностей:

    ■ Отправитель не дожидается ACK для каждого из посылаемых сегментов данных. Единственным ограничением на пересылку является размер приемного окна (например, отправитель должен пересылать только 4 К однобайтовых сегментов).

    ■ Предположим, что отправитель посылает данные в нескольких очень коротких сегментах (например, по 80 байт). В этом случае данные могут быть переформатированы для более эффективной передачи (например, в единый сегмент).

    10.8 Заголовок TCP

    На рис. 10.14 показан формат сегмента (заголовок TCP и данные). Заголовок начинается с идентификаторов портов источника и назначения. Следующее далее поле порядкового номера (sequence number) указывает позицию в исходящем потоке данных, которую занимает данный сегмент. Поле ACK (подтверждения) содержит сведения о предполагаемом следующем сегменте, который должен появиться во входном потоке данных.

    Рис. 10.14. Сегмент TCP

    Существуют шесть флагов:

    URG Равен 1 для срочных данных
    ACK Равен 1 для всех сегментов, кроме начального
    PSH Указывает на необходимость своевременной доставки данных
    RST Индикатор ошибки, используется и для завершения сеанса
    SYN Равен 1 во время установки соединения
    FIN Равен 1 при нормальном закрытии

    Поле смещения данных (Data Offset) содержит размер заголовка TCP в 32-разрядных словах. Заголовок TCP должен заканчиваться на 32-битной границе.

    10.8.1 Вариант максимального размера сегмента

    Параметр "максимальный размер сегмента" (maximum segment size — MSS) применяется для объявления о наибольшем куске данных, который может быть принят и обработан системой. Однако название несколько неточно. Обычно в TCP сегмент рассматривается как заголовок плюс данные. Однако максимальный размер сегмента определяется как:

    Размер наибольшей датаграммы, которую можно принять, – 40

    Другими словами, MSS отражает наибольшую полезную нагрузку в приемнике при длине заголовков TCP и IP по 20 байт. Если имеются дополнительные параметры, их длину следует вычесть из общего размера. Следовательно, количество данных, которые можно переслать в сегменте, определяется как:

    Заявленное значение MSS + 40 – (сумма длин заголовков TCP и IP)

    Обычно партнеры обмениваются значениями MSS в начальных сообщениях SYN при открытии соединения. Если система не анонсирует величину максимального размера сегмента, используется значение по умолчанию в 536 байт.

    Размер максимального сегмента кодируется 2-байтовой вводной частью со следующим далее 2-байтовым значением, т.е. наибольшая величина будет составлять 216-1 (65 535 байт).

    MSS накладывает жесткое ограничение на пересылаемые в TCP данные: приемник не сможет обработать большие значения. Однако отправитель использует сегменты меньшего размера, поскольку для соединения определяется еще размер MTU по пути следования.

    10.8.2 Использование полей заголовка в запросе на соединение

    Первый сегмент, посылаемый для открытия соединения, имеет значение флага SYN, равное 1, и флага ACK — 0. Начальный SYN является единственным сегментом, имеющим поле ACK со значением 0. Отметим, что средства защиты пользуются этим признаком для выявления входных запросов на сеанс TCP.

    Поле порядкового номера содержит начальный порядковый номер (initial sequence number), поле окна — начальный размер приемного окна. Единственным определенным на сегодняшний момент параметром TCP является максимальный размер сегмента (когда он не указан, используется значение по умолчанию в 536 байт), который предполагает получать TCP. Это значение занимает 32 бита и обычно присутствует в запросе на соединение в поле вариантов (Option). Длина заголовка TCP, содержащего значение MSS, составляет 24 байта.

    10.8.3 Использование полей заголовка в ответе на запрос соединения

    В разрешающем ответе на запрос соединения оба флага (SYN и ACK) равны 1. Отвечающая система указывает начальный порядковый номер в соответствующем поле, а размер приемного окна — в поле Window. Максимальный размер сегмента, который желает использовать получатель, обычно находится в ответе на запрос о соединении (в поле вариантов). Это значение может отличаться от значения запрашивающей соединение стороны, т.е. могут применяться две разные величины.

    Запрос на соединение может быть отклонен посредством указания в ответе флага сброса (RST) со значением 1.

    10.8.4 Выбор начального порядкового номера

    Спецификация TCP предполагает, что во время установки соединения каждая из сторон выбирает начальный порядковый номер (по текущему значению 32-разрядного внутреннего таймера). Как это выполняется?

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

    Поэтому другая сторона в самом конце соединения может не знать о том, что ее партнер прошел через крах и его работа затем была восстановлена. Все это приведет к серьезным сбоям в работе, особенно когда проходит долгое время, пока старые данные не пройдут по сети и не смешаются с данными от вновь созданного соединения. Выбор по таймеру старта с обновлением (fresh start) позволяет исключить подобные проблемы. Старые данные будут иметь иную нумерацию, чем диапазон порядковых номеров нового соединения. Хакеры при фальсификации IP-адреса источника для доверительного хоста пытаются получить доступ к компьютерам с помощью указания в сообщении предсказуемого начального порядкового номера. Криптографическая функция хеширования на основе внутренних ключей служит лучшим способом для выбора защищенных начальных номеров.

    10.8.5 Общепринятое использование полей

    При подготовке заголовка TCP к пересылке порядковый номер первого октета передаваемых данных указывается в поле последовательного номера (Sequence Number).

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

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

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

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

    Флаг RESET (сброс) имеет значение 1, когда следует аварийно завершить соединение. Этот же флаг устанавливается в ответе при поступлении сегмента, не связанного ни с одним из текущих соединений TCP.

    Флаг FIN устанавливается в 1 для сообщений о закрытии соединения.


    10.8.6 Контрольная сумма

    Контрольная сумма IP предназначена только для заголовка IP, а контрольная сумма TCP вычисляется для всего сегмента, а также для псевдозаголовка, созданного из заголовка IP. Во время вычисления контрольной суммы TCP соответствующее поле имеет значение 0. На рис. 10.15 показан псевдозаголовок, очень напоминающий тот, что используется в контрольной сумме UDP.

    Рис. 10.15. Поле псевдозаголовка включается в контрольную сумму TCP

    Длина TCP вычисляется сложением длины заголовка TCP с длиной данных. Контрольная сумма TCP является обязательной, не как в UDP. Контрольная сумма поступившего сегмента сначала вычисляется приемником, а затем сравнивается с содержимым поля контрольной суммы заголовка TCP. Если значения не совпадут, сегмент отбрасывается.

    10.9 Пример сегмента TCP

    Рис. 10.16, протокол работы анализатора Sniffer компании Network General, представляет собой последовательность сегментов TCP. Первые три сегмента устанавливают соединение между клиентом и сервером Telnet. В последнем сегменте переносится 12 байт данных.

    Рис. 10.16. Отображение заголовка TCP анализатором Sniffer

    Анализатор Sniffer транслирует большинство значений в десятичный вид. Однако значения флагов выводятся как шестнадцатеричные. Флаг со значением 12 представляет собой 010010. Контрольная сумма выводится тоже в шестнадцатеричном виде.

    10.10 Поддержка работы сеанса

    10.10.1 Зондирование окна

    Скоростной отправитель и медленный получатель могут сформировать приемное окно размером в 0 байт. Этот результат называется закрытием окна (close window). Когда появляется свободное место для обновления размера приемного окна, используется ACK. Однако, если такое сообщение будет потеряно, обе стороны должны будут ожидать до бесконечности.

    Для избежания такой ситуации отправитель устанавливает сохраняемый таймер (persist timer) при закрытии премного окна. Значением таймера берется тайм-аут повторной пересылки. По завершении работы таймера партнеру отсылается сегмент зондирования окна (window probe; в некоторых реализациях в него включаются и данные). Зондирование заставляет партнера посылать назад ACK, который сообщает о текущем статусе окна.

    Если окно все еще остается нулевого размера, удваивается значение сохраняемого таймера. Этот процесс повторяется, пока значение таймера не достигнет максимума в 60 с. TCP продолжит посылать сообщения зондирования каждые 60 с — до открытия окна, до завершения процесса пользователем или до завершения по тайм-ауту приложения.

    10.11 Завершение сеанса

    10.11.1 Тайм-аут

    Работа партнера по соединению может завершиться крахом либо полностью прерваться вследствие неисправности шлюза или связи. Чтобы предотвратить повторную пересылку данных в TCP, существует несколько механизмов.

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

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

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

    10.11.2 Поддержание соединения

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

    Однако любое соединение — активное или неактивное — занимает много памяти компьютера. Некоторым администраторам нужно возвратить в системы неиспользованные ресурсы. Поэтому многие реализации TCP способны посылать сообщение о поддержании соединения (keep-alive), тестирующее неактивные соединения. Такие сообщения периодически отправляются партнеру для проверки его существования в сети. В ответ должны поступать сообщения ACK. Использование сообщений о поддержании соединения не является обязательным. Если в системе имеется такая возможность, приложение может отменить ее собственными средствами. Предполагаемый период по умолчанию для тайм-аута поддержания соединения составляет целых два часа!

    Вспомним, что приложение может установить собственный таймер, по которому на своем уровне и будет принимать решение о завершении соединения.

    10.12 Производительность

    Насколько эффективна работа TCP? На производительность ресурсов влияют многие факторы, из которых основными являются память и полоса пропускания (см. рис. 10.17).

    Рис. 10.17. Факторы производительности TCP

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

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

    Например, если источник может отсылать данные со скоростью 10 000 байт/с, а на возврат ACK тратится 2 с, то на другой стороне нужно обеспечить приемное окно размером не менее 20 000 байт, иначе поток данных не будет непрерывным. Приемный буфер в 10 000 байт вполовину снизит пропускную способность.

    Еще одним важным фактором для производительности является способность хоста реагировать на высокоприоритетные события и быстро выполнять контекстное переключение, т.е. завершать одни операции и переключаться на другие. Хост может интерактивно поддерживать множество локальных пользователей, пакетные фоновые процессы и десятки одновременных коммуникационных соединений. Контекстное переключение позволяет обслуживать все эти операции, скрывая нагрузки на систему. Реализации, в которых проведена интеграция TCP/IP с ядром операционной системы, могут существенно снизить нагрузки от использования контекстного переключения.

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

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

    Предположим, что сетевое окружение совершенно: имеются достаточные ресурсы и контекстное переключение выполняется быстрее, чем ковбои выхватывают свои револьверы. Будет ли получена прекрасная производительность?

    Не всегда. Имеет значение и качество разработки программного обеспечения TCP. За долгие годы в различных реализациях TCP были диагностированы и решены многие проблемы производительности. Можно считать, что наилучшим будет программное обеспечение, соответствующее документу RFC 1122, в котором определены требования к коммуникационному уровню хостов Интернета.

    Не менее важно исключение синдрома "бестолкового окна" и применение алгоритмов Джекобсона, Керна и Партриджа (эти интересные алгоритмы будут рассмотрены ниже).

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

    10.13 Алгоритмы повышения производительности

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

    ■ Медленный старт (slow start) мешает использованию большой доли сетевого трафика для нового сеанса, что может привести к непроизводительным потерям.

    ■ Излечение от синдрома "бестолкового окна" (silly window syndrome) предохраняет плохо разработанные приложения от перегрузки сети сообщениями.

    ■ Задержанный ACK (delayed ACK) снижает перегрузку посредством сокращения количества независимых сообщений подтверждения пересылки данных.

    ■ Вычисляемый тайм-аут повторной пересылки (computing retransmission timeout) основывается на согласовании реального времени сеанса, уменьшая объем ненужных повторных пересылок, но при этом не вызывает больших задержек для реально необходимых обменов данными.

    ■ Торможение пересылки TCP при перегрузках в сети позволяет маршрутизаторам вернуться в исходный режим и совместно использовать сетевые ресурсы для всех сеансов.

    ■ Отправка дублированных ACK (duplicate ACK) при получении сегмента вне последовательности отправки позволяет партнерам выполнить повторную пересылку до наступления тайм-аута.

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

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

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

    Нагрузочное окно (congestion window) начинается с размера в 1 сегмент. Для каждого сегмента с успешно полученным ACK размер нагрузочного окна увеличивается на 1 сегмент, пока оно остается меньше, чем приемное окно. Если сеть не перегружена, нагрузочное окно постепенно достигнет размера приемного окна. При нормальном состоянии пересылки размеры этих окон будут совпадать.

    Отметим, что медленный старт — не такой уж и медленный. После первого ACK размер нагрузочного окна равен 2-м сегментам, а после успешного получения ACK для двух сегментов размер может увеличиться до 8 сегментов. Другими словами, размер окна увеличивается экспоненциально.

    Предположим, что вместо получения ACK возникла ситуация тайм-аута. Поведение нагрузочного окна в таком случае рассматривается ниже.

    10.13.2 Синдром "бестолкового окна"

    В первых реализациях TCP/IP разработчики столкнулись с феноменом синдрома "бестолкового окна" (Silly Window Syndrome — SWS), который проявлялся достаточно часто. Для понимания происходящих событий рассмотрим следующий сценарий, приводящий к нежелательным последствиям, но вполне возможный:

    1. Передающее приложение быстро отсылает данные.

    2. Принимающее приложение читает из входного буфера по 1 байту данных (т.е. медленно).

    3. Входной буфер после чтения быстро заполняется.

    4. Принимающее приложение читает 1 байт, и TCP отправляет ACK, означающий "Я имею свободное место для 1 байта данных".

    5. Передающее приложение отправляет по сети пакет TCP из 1 байта.

    6. Принимающий TCP посылает ACK, означающий "Спасибо. Я получил пакет и не имею больше свободного места".

    7. Принимающее приложение опять читает 1 байт и отправляет ACK, и весь процесс повторяется.

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

    Реальные ситуации, конечно, не столь экстремальны. Быстрый отправитель и медленный получатель будут обмениваться небольшими (относительно максимального размера сегмента) кусками данных и переключаться по почти заполненному приемному окну. На рис. 10.18 показаны условия для появления синдрома "бестолкового окна".

    Рис. 10.18. Буфер приемного окно с очень малым размером свободного пространства

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

    minimum(1/2 входного буфера, Максимальный размер сегмента)

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

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

    10.13.3 Алгоритм Нейгла

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

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

    10.13.4 Задержанный ACK

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

    ■ Можно подтвердить прием нескольких сегментов одним ACK.

    ■ Принимающее приложение способно получить некоторый объем данных в пределах интервала тайм-аута, т.е. в ACK может попасть выходной заголовок, и не потребуется формирование отдельного сообщения.

    С целью исключения задержек при пересылке потока полноразмерных сегментов (например, при обмене файлами), ACK должен отсылаться, по крайней мере, для каждого второго полного сегмента.

    Многие реализации используют тайм-аут в 200 мс. Но задержанный ACK не снижает скорость обмена. При поступлении короткого сегмента во входном буфере остается еще достаточно свободного места для получения новых данных, а отправитель может продолжить пересылку (кроме того, повторная пересылка обычно выполняется гораздо медленнее). Если же поступает целый сегмент, нужно в ту же секунду ответить на него сообщением ACK.

    10.13.5 Тайм-аут повторной пересылки

    После отправки сегмента TCP устанавливает таймер и отслеживает поступление ACK. Если ACK не получен в течение периода тайм-аута, TCP выполняет повторную пересылку сегмента (ретрансляцию). Однако каким должен быть период тайм-аута?

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

    Как выбрать правильный промежуток для тайм-аута? Значение, пригодное для высокоскоростной локальной сети, не подойдет для удаленного соединения со множеством попаданий. Значит, принцип "одно значение для любых условий" явно непригоден. Более того, даже для существующего конкретного соединения могут измениться сетевые условия, а задержки — увеличиться или снизиться.

    Алгоритмы Джекобсона, Керна и Партриджа (описанные в статьях Congestion Avoidance and Control, Van Jacobson, и Improving Round-Trip Time Estimates in Reliable Transport Protocols, Karn и Partridge) позволяют адаптировать TCP к изменению сетевых условий. Эти алгоритмы рекомендованы к использованию в новых реализациях. Мы кратко рассмотрим их ниже.

    Здравый смысл подсказывает, что наилучшей основой оценки правильного времени тайм-аута для конкретного соединения может быть отслеживание времени цикла (round-trip time) как промежутка между отправкой данных и получением подтверждения об их приеме.

    Хорошие решения для следующих величин можно получить на основе элементарных статистических сведений (см. рис. 10.19), которые помогут вычислить время тайм-аута. Однако не нужно полагаться на усредненные величины, поскольку более половины оценок будет больше, чем среднестатистическая величина. Рассмотрев пару отклонений, можно получить более правильные оценки, учитывающие нормальное распределение и снижающие слишком долгое время ожидания повторной пересылки.

    Рис. 10.19. Распределение значений времени цикла

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

    Последнее отклонение = | Последний цикл - Средняя величина |

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

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

    Например, если 1000 значений дали среднестатистическую величину в 170 единиц, но далее были замерены 50 значений со средним в 282, то текущее среднее будет:

    170×1000/1050 + 282×50/1050 = 175

    Более резонной будет величина сглаженного времени цикла (Smoothed Round-Trip Time — SRTT), которая учитывает приоритет более поздних значений:

    Новое SRTT = (1 – α)×(старое SRTT) + α×Последнее значение цикла

    Значение α находится между 0 и 1. Увеличение а приводит к большему влиянию текущего времени цикла на сглаженное среднее значение. Поскольку компьютеры быстро могут выполнять деление на степени числа 2, сдвигая двоичные числа направо, для α всегда выбирается значение (1/2)n (обычно 1/8), поэтому:

    Новое SRTT = 7/8×старое SRTT + 1/8×Последнее время цикла

    В таблице 10.2 показано, как формула для SRTT подстраивается под текущее значение SRTT в 230 единиц, когда изменение в сетевых условиях приводит к последовательному увеличению времени цикла (при условии, что не наступает тайм-аут). Значения в столбце 3 используются как значения столбца 1 для следующей строки таблицы (т.е. как старое SRTT).


    Таблица 10.2 Вычисление сглаженного времени цикла

    Старое SRTT Самое последнее RTT (7/8)×(старое SRTT) + (1/8)×(RTT)
    230.00 294 238.00
    238.00 264 241.25
    241.25 340 253.59
    253.59 246 252.64
    252.64 201 246.19
    246.19 340 257.92
    257.92 272 259.68
    259.68 311 266.10
    266.10 282 268.09
    268.09 246 265.33
    265.33 304 270.16
    270.16 308 274.89
    274.89 230 269.28
    269.28 328 276.62
    276.62 266 275.29
    275.29 257 273.00
    273.00 305 277.00

    Теперь возникает вопрос о выборе значения для тайм-аута повторной пересылки. Анализ величин времени цикла показывает существенное отклонение этих значений от текущей средней величины. Имеет смысл установить границу для величины отклонений (девиаций). Хорошие величины для тайм-аута повторной пересылки (в стандартах RFC эту величину именуют Retransmission TimeOut — RTO) дает следующая формула с ограничением сглаженного отклонения (SDEV):

    Т = Тайм-аут повторной пересылки = SRTT + 2×SDEV

    Именно эта формула рекомендована в RFC 1122. Однако некоторые реализации используют другую:

    Т = SRTT + 4×SDEV

    Для вычисления SDEV сначала определяют абсолютное значение текущего отклонения:

    DEV = | Последнее время цикла – старое SRTT |

    Затем используют формулу сглаживания, чтобы учесть последнее значение:

    Новое SDEV = 3/4×старое SDEV + 1/4×DEV

    Остается один вопрос — какие взять начальные значения? Рекомендуется:

    Начальный тайм-аут = 3 с

    Начальный SRTT = 0

    Начальный SDEV = 1,5 с

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

    10.13.6 Пример статистики

    Насколько успешно будет работать вычисленный выше тайм-аут? При реализации полученного значения наблюдались значительные повышения производительности. Примером могут служить статистические данные команды netstat, полученные на системе tigger — сервере Интернета, к которому обращается множество хостов со всего мира.

    tcp:

    1301644 packets sent

     879137 data packets (226966295 bytes)

     21815 data packets (8100927 bytes) retransmitted


    2012869 packets received

     762469 acks (for 226904227 bytes)

     35803 duplicate acks

     0 acks for unsent data

     1510769 packets (314955304 bytes) received in-sequence

     9006 completely duplicate packets (867042 bytes)

     74 packets with some dup. data (12193 bytes duped)

     13452 out-of-order packets (2515087 bytes)

    Системой tigger были повторно переданы менее чем 2,5% сегментов данных TCP. Для полутора миллионов входящих сегментов данных (остальные являются чистыми сообщениями ACK) дублированы были только 0,6%. При этом следует учитывать, что уровень потерь во входных данных примерно соответствует уровню для выходных сегментов. Таким образом, бесполезный трафик повторной пересылки составляет около 0,6% от общего трафика.

    10.13.7 Вычисления после повторной отправки

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

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

    10.13.8 Действия после повторной пересылки

    Но что происходит до получения подтверждения? После повторной пересылки поведение TCP радикально меняется в основном из-за потери данных от перегрузки в сети. Следовательно, реакцией на повторную отправку данных будет:

    ■ Снижение скорости повторной пересылки

    ■ Борьба с перегрузкой сети с помощью сокращения общего трафика

    10.13.9 Экспоненциальное торможение

    После повторной пересылки удваивается интервал тайм-аута. Однако что произойдет при повторном переполнении таймера? Данные будут оправлены еще раз, а период повторной пересылки снова удвоится. Этот процесс называется экспоненциальным торможением (exponential backoff).

    Если продолжает проявляться неисправность сети, период тайм-аута будет удваиваться до достижения предустановленного максимального значения (обычно — 1 мин). После тайм-аута может быть отправлен только один сегмент. Тайм-аут наступает и при превышении заранее установленного значения для количества пересылок данных без получения ACK.

    10.13.10 Снижение перегрузок за счет уменьшения пересылаемых по сети данных

    Сокращение объема пересылаемых данных несколько сложнее, чем рассмотренные выше механизмы. Оно начинает работать, как и уже упомянутый медленный старт. Но, поскольку устанавливается граница для уровня трафика, который может в начальный момент привести к проблемам, будет реально замедляться скорость обмена вследствие увеличения размера нагрузочного окна по одному сегменту. Нужно установить значения границы для реального сокращения скорости отправки. Сначала вычисляется граница опасности (danger threshold):

    Граница – 1/2 minimum (текущее нагрузочное окно, приемное окно партнера)

    Если полученная величина будет более двух сегментов, ее используют как границу. Иначе размер границы устанавливается равным двум сегментам. Полный алгоритм восстановления требует:

    ■ Установить размер нагрузочного окна в один сегмент.

    ■ Для каждого полученного ACK увеличивать размер нагрузочного окна на один сегмент, пока не будет достигнута граница (что очень напоминает механизм медленного старта).

    ■ После этого с каждым полученным ACK к нагрузочному окну добавлять меньшее значение, которое выбирается на основе скорости увеличения по одному сегменту для времени цикла (увеличение вычисляется как MSS/N, где N — размер нагрузочного окна в сегментах).

    Сценарий для идеального варианта может упрощенно представить работу механизма восстановления. Предположим, что приемное окно партнера (и текущее нагрузочное окно) имело до выявления тайм-аута размер в 8 сегментов, а граница определена в 4 сегмента. Если принимающее приложение мгновенно читает данные из буфера, размер приемного окна останется равным 8 сегментам.

    ■ Отправляется 1 сегмент (нагрузочное окно = 1 сегмент).

    ■ Получен ACK — отправляется 2 сегмента.

    ■ Получен ACK для 2 сегментов — посылается 4 сегмента, (достигается граница).

    ■ Получен ACK для 4 сегментов. Посылается 5 сегментов.

    ■ Получен ACK для 5 сегментов. Посылается 6 сегментов.

    ■ Получен ACK для 6 сегментов. Посылается 7 сегментов.

    ■ Получен ACK для 7 сегментов. Посылается 8 сегментов (нагрузочное окно по размеру снова стало равно приемному окну).

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

    Рис. 10.20. Ограничение скорости пересылки во время перегрузки

    10.13.11 Дублированные ACK

    В некоторых реализациях применяется необязательная возможность — так называемая быстрая повторная пересылка (fast retransmit) — с целью ускорить повторную отправку данных при определенных условиях. Ее основная идея связана с отправкой получателем дополнительных ACK, указывающих на пробел в принятых данных.

    Принимая сегмент, поступивший не по порядку, получатель отсылает обратно ACK, указывающий на первый байт потерянных данных (см. рис. 10.21).

    Рис. 10.21. Дублированные ACK

    Отправитель не выполняет мгновенной повторной пересылки данных, поскольку IP может и в нормальном режиме доставлять данные получателю без последовательности отправки. Но когда получено несколько дополнительных ACK на дублирование данных (например, три), то отсутствующий сегмент будет отправлен, не дожидаясь завершения тайм-аута.

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

    10.13.12 Что делается после подавления источника?

    В соответствии со стандартом Host Requirements (требования к хостам) TCP должен выполнять тот же самый медленный старт, как это описано выше, при подавлении источника (source quench). Однако сообщение об этом не является целенаправленным или эффективным, поскольку получившее это сообщение соединение может и не создавать слишком большого трафика. Текущая спецификация Router Requirements (требования к маршрутизаторам) указывает, что маршрутизаторы не должны посылать сообщений о подавлении источника.

    10.13.13 Статистика TCP

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

    tcp:

    1301644 packets sent                              
    Пакетами именуются сегменты.

    879137 data packets (226966295 bytes)

    21815 data packets (8100927 bytes) retransmitted  
    Повторная пересылка.

    132957 ack-only packets (104216 delayed)          
    Отметим большое количество

     задержанных ACK.

    4 URG only packets

    1038 window probe packets                         
    Зондирование открытия окна

     нулевого размера.

    248582 window update packets

    22413 control packets                             
    Это сообщения SYN и FIN.

    2012869 packets received

    762469 acks (for 226904227 bytes)

    35803 duplicate acks                              
    Сигнал о пакетах, прибывших

     вне последовательности.

    0 acks for unsent data

    1510769 packets (314955304 bytes)

      received in-sequence

    9006 completely duplicate packets (867042 bytes)  
    Результат тайм-аута при реальной

     доставке данных.

    74 packets with some dup. data (12193 bytes duped)
    С целью большей эффективности

     некоторые данные при повторной отправке были перепакетированы для включения дополнительных байт.

    13452 out-of-order packets (2515087 bytes)

    530 packets (8551 bytes) of data after window      
    Возможно, эти данные были

     включены в сообщения зондирования.

    526 window probes

    14158 window update packets

    402 packets received after close                   
    Это последующие повторные

     отправки.

    108 discarded for bad checksums                    
    Неверная контрольная сумма TCP.

    0 discarded for bad header offset fields

    7 discarded because packet too short

    6378 connection requests

    9539 connection accepts

    14677 connections established (including accepts)

    18929 connections closed (including 643 drops)

    4100 embryonic connections dropped

    572187 segments updated rtt (of 587397 attempts)  
    Неудачные попытки изменения

     времени цикла, поскольку ACK не успел прийти до завершения тайм-аута,

    11014 retransmit timeouts

    26 connections dropped by rexmit timeout           
    Последующие неудачные попытки

     повторной отправки, что указывает на потерянное соединение.

    1048 persist timeouts                             
    Тайм-ауты по зондированию

     нулевого окна.

    535 keepalive timeouts                            
    Тайм-ауты по проверке

     неработающего соединения.

    472 connections dropped by keepalive

    10.14 Соответствие требованиям разработчика

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

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

    10.15 Барьеры для производительности

    TCP доказал свою гибкость, работая в сетях со скоростью обмена в сотни или миллионы бит за секунду. Этот протокол позволил достичь хороших результатов в современных локальных сетях с топологиями Ethernet, Token-Ring и Fiber Distributed Data Interface (FDDI), а также для низкоскоростных линий связи или соединений на дальние расстояния (подобных спутниковым связям).

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

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

    ■ Максимальный размер сегмента приемника — 1 Кбайт.

    ■ Приемное окно — 4 Кбайт.

    ■ Полоса пропускания позволяет пересылать по два сегмента за 1 с.

    ■ Принимающее приложение поглощает данные по мере их поступления.

    ■ Сообщения ACK прибывают через 2 с.

    Отправитель способен посылать данные непрерывно. Ведь когда выделенный для окна объем будет заполнен, прибывает ACK, разрешающий отправку другого сегмента:

    SEND SEGMENT 1.

    SEND SEGMENT 2.

    SEND SEGMENT 3.

    SEND SEGMENT 4.

    Через 2 с:

    RECEIVE ACK OF SEGMENT 1, CAN SEND SEGMENT 5.

    RECEIVE ACK OF SEGMENT 2, CAN SEND SEGMENT 6.

    RECEIVE ACK OF SEGMENT 3, CAN SEND SEGMENT 7.

    RECEIVE ACK OF SEGMENT 4, CAN SEND SEGMENT 8.

    Еще через 2 с:

    RECEIVE ACK OF SEGMENT 5, CAN SEND SEGMENT 9.

    . . .

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

    Окно = Полоса пропускания×Время цикла

    Хотя пример несколько преувеличен (для обеспечения более простых чисел), малое окно может привести к проблемам при соединениях через спутниковые связи с большой задержкой.

    Теперь рассмотрим, что происходит с высокоскоростными соединениями. Например, если полоса пропускания и скорость пересылки измеряются 10 млн. бит в секунду, но время цикла составляет 100 мс (1/10 секунды), то для непрерывного потока приемное окно должно хранить, по крайней мере, 1 000 000 бит, т.е. 125 000 байт. Но наибольшее число, которое можно записать в поле заголовка для приемного окна TCP, равно 65 536.

    Другая проблема возникает при высоких скоростях обмена, поскольку порядковые номера очень быстро закончатся. Если по соединению можно будет пересылать данные со скоростью 4 Гбайт/с, то порядковые номера должны обновляться в течение каждой секунды. Не будет возможности различить старые дублирующие датаграммы, которые были отсрочены более чем на секунду при перемещении по Интернету, от свежих новых данных.

    Сейчас активно проводятся новые исследования для улучшения TCP/IP и устранения упомянутых выше препятствий.

    10.16 Функции TCP

    Данная глава посвящена многочисленным функциям TCP. Ниже перечислены основные из них:

    ■ Связывание портов с соединениями

    ■ Инициализация соединений посредством трехшагового подтверждения

    ■ Выполнение медленного старта, исключающего перегрузку сети

    ■ Сегментация данных при пересылке

    ■ Нумерация данных

    ■ Обработка поступающих дублированных сегментов

    ■ Вычисление контрольных сумм

    ■ Регулирование потока данных через приемное окно и окно отправки

    ■ Завершение соединения установленным способом

    ■ Прерывание соединения

    ■ Пересылка срочных данных

    ■ Положительное подтверждение повторной пересылки

    ■ Вычисление тайм-аута повторной пересылки

    ■ Снижение обратного трафика при перегрузке сети

    ■ Сигнализация поступления сегментов не по порядку

    ■ Зондирование закрытия приемного окна

    10.17 Состояния TCP

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

    Ниже мы кратко рассмотрим типичную смену состояний сервера и клиента, расположенных на разных концах соединения. Мы не ставим целью дать исчерпывающее описание всех возможных состояний при пересылке данных. Оно приведено в RFC 793 и документе Host Requirements.

    Во время установки соединений сервер и клиент проходят схожие последовательности состояний. Состояния сервера показаны в таблице 10.3, а состояния клиента — в таблице 10.4.


    Таблица 10.3 Последовательность состояний сервера

    Состояние сервера Событие Описание
    CLOSED (закрыто) Фиктивное состояние перед началом установки соединения.
    Пассивное открытие серверным приложением.
    LISTEN (отслеживание) Сервер ожидает соединения с клиентом.
    Сервер TCP получает SYN и посылает SYN/ACK. Сервер получил SYN и послал SYN/ACK. Переходит к ожиданию ACK.
    SYN-RECEIVED Сервер TCP получает ACK.
    ESTABLISHED (установлено) Получен ACK, открыто соединение.

    Таблица 10.4 Последовательность состояний клиента

    Состояние сервера Событие Описание
    CLOSED Фиктивное состояние перед началом соединения.
    Клиентское приложение запрашивает соединение. Клиент TCP посылает SYN.
    SYN-SENT Клиент TCP послал SYN серверу.
    Клиент TCP получает SYN/ACK и посылает ACK. Клиент получил SYN/ACK от сервера и отправил обратно ACK.
    ESTABLISHED (установлено) Можно перейти к пересылке данных.

    Если бы партнеры одновременно пытались установить соединение друг с другом (что случается крайне редко), каждый прошел бы через состояния CLOSED, SYN-SENT, SYN-RECEIVED и ESTABLISHED.

    Конечные стороны соединения остаются в состоянии ESTABLISHED, пока одна из сторон не приступит к закрытию соединения, послав сегмент FIN. В процессе обычного закрытия сторона, инициирующая это закрытие, проходит через состояния, показанные в таблице 10.5. Ее партнер проходит через состояния, представленные в таблице 10.6.


    Таблица 10.5 Последовательность состояний стороны, закрывающей соединение

    Состояния закрывающей стороны Событие Описание
    ESTABLISHED Локальное приложение запрашивает закрытие соединения.
    TCP посылает FIN/ACK.
    FIN-WAIT-1 Закрывающая сторона ожидает ответа партнера. Напомним, что от партнера все еще могут прибывать новые данные.
    TCP получает ACK.
    FIN-WAIT-2 Закрывающая сторона получила ACK от партнера, но еще не пришел FIN. Закрывающая сторона ожидает FIN, принимая поступающие данные.
    TCP получает FIN/ACK.
    Посылает ACK.
    TIME-WAIT Соединение поддерживается в неопределенном состоянии, чтобы позволить прибыть или отбросить все еще существующие в сети дублированные данные или дублированный FIN. Период ожидания вдвое больше оценки максимального времени жизни сегмента.
    CLOSED Удалена вся информация о соединении.

    Таблица 10.6 Последовательность состояний партнера по закрытию соединения

    Состояние партнера Событие Описание
    ESTABLISHED TCP получает FIN/ACK.
    CLOSE-WAIT Прибыл FIN.
    TCP посылает ACK.
    TCP ожидает от своего приложения закрытия соединения. В этот момент приложение может посылать достаточно большое количество данных.
    Локальное приложение инициализирует закрытие соединения.
    TCP посылает FIN/ACK.
    LAST-ACK TCP ожидает конечный ACK.
    TCP получает ACK.
    CLOSED Удалена вся информация о соединении.

    10.17.1 Анализ состояний соединения TCP

    Команда netstat -an позволяет проверить текущее состояние соединения. Ниже показаны соединения в состояниях listen, startup, established, closing и time-wait.

    Отметим, что номер порта соединения указан в конце каждого локального и внешнего адреса. Видно, что имеется трафик TCP как для входной, так и для выходной очередей.

    > netstat -an

    Active Internet connections

    Pro Recv-Q Send-Q Local Address       Foreign Address     (state)

    Tcp    0      0   128.121.50.145.25   128.252.223.5.1526  SYN_RCVD

    Tcp    0      0   128.121.50.145.25   148.79.160.65.3368  ESTABLISHED

    Tcp    0      0   127.0.0.1.1339      127.0.0.1.111       TIME_WAIT

    Tcp    0    438   128.121.50.145.23   130.132.57.246.2219 ESTABLISHED

    Tcp    0      0   128.121.50.145.25   192.5.5.1.4022      TIME_WAIT

    Tcp    0      0   128.121.50.145.25   141.218.1.100.3968  TIME_WAIT

    Tcp    0    848   128.121.50.145.23   192.67.236.10.1050  ESTABLISHED

    Tcp    0      0   128.121.50.145.1082 128.121.50.141.6000 ESTABLISHED

    Tcp    0      0   128.121.50.145.1022 128.121.50.141.1017 ESTABLISHED

    Tcp    0      0   128.121.50.145.514  128.121.50.141.1020 CLOSE_WAIT

    Tcp    0   1152   128.121.50.145.119  192.67.239.23.3572  ESTABLISHED

    Tcp    0      0   128.121.50.145.1070 192.41.171.5.119    TIME_WAIT

    Tcp  579   4096   128.121.50.145.119  204.143.19.30.1884  ESTABLISHED

    Tcp    0      0   128.121.50.145.119  192.67.243.13.3704  ESTABLISHED

    Tcp    0     53   128.121.50.145.119  192.67.236.218.2018 FIN_WAIT_1

    Tcp    0      0   128.121.50.145.119  192.67.239.14.1545  ESTABLISHED

    Tcp    0      0   *.19                *.*                 LISTEN

    Tcp    0      0   *.13                *.*                 LISTEN

    Tcp    0      0   *.9                 *.*                 LISTEN

    Tcp    0      0   *.7                 *.*                 LISTEN

    Tcp    0      0   *.31                *.*                 LISTEN

    10.18 Замечания о реализациях

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

    Даже RFC 1122 (документ Host Requirements — требования к хостам) оставляет достаточную свободу для вариаций. Каждая из реализуемых функций маркируется определенным уровнем совместимости:

    ■ MUST (Необходимо)

    ■ SHOULD (Рекомендовано)

    ■ MAY (Разрешено)

    ■ SHOULD NOT (Не рекомендовано)

    ■ MUST NOT (Не нужно)

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

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

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

    Фактически разработчики основывают свои комплекты инструментов на программном интерфейсе Socket, заимствованном из Berkeley. Значение программного интерфейса возросло с появлением WINSock (Windows Socket), что привело к быстрому увеличению новых приложений для настольных систем, которые могли работать поверх любого интерфейса WINSock, совместимого со стеком TCP/IP.

    10.19 Дополнительная литература

    Оригинал стандарта TCP определен в RFC 793. Модернизации, исправления, и требования совместимости рассмотрены в RFC 1122. Керн (Каш) и Партридж (Partridge) опубликовали статью Improving Round-Trip Estimates in Reliable Transport Protocols в журнале Proceedings of the ACM SIGCOMM 1987. Статья Джекобсона (Jacobson) Congestion Avoidance and Control появилась в Proceedings of the ACM SIGCOMM 1988 Workshop. Джекобсон издал также несколько RFC, пересматривающих алгоритмы повышения производительности.








    Главная | В избранное | Наш E-MAIL | Прислать материал | Нашёл ошибку | Наверх