Friday, May 18th

Last update12:13:00 PM GMT

Вы находитесь на: FreeBSD Сетевые протоколы Обработка вывода TCP

Обработка вывода TCP

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

 

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

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

Отправка данных

Наиболее очевидной причиной вызова tcpoutput() выходного модуля является то, что пользователь записал в сокет новые данные. Операции записи делаются посредством вызова процедуры tcpusrsend(). (Вспомните, что sosend() при необходимости ожидает появления достаточного места в буфере отправки сокета, а затем копирует данные пользователя в цепочку mbuf, которая передается протоколу процедурой tcpusrsend().) Действием tcpusrsend() является просто помещение новых выходных данных в буфер отправки сокета с помощью sbappendstream() и вызов tcp_output(). Если процедура tcp_output() допускает управление потоком, то она отправит данные немедленно.
Фактическая операция отправки не отличается существенно от операции для сокета UDP-дейтаграмм. Различие в том, что заголовок более сложный и должны быть инициализированы дополнительные поля, а отправленные данные являются просто копией данных пользователя. Однако для операций отправки, достаточно больших для того, чтобы sosend() поместил данные во внешние кластеры mbuf, копирование осуществляется путем создания новой ссылки на кластер данных. Копия должна быть сохранена в буфере отправки сокета на случай необходимости повторной отправки. Также, если число октетов данных больше, чем размер одного сегмента максимального размера, в единственном вызове будет создано и отправлено несколько пакетов.

Процедура tcpoutput() выделяет mbuf для сохранения заголовка выходного пакета и копирует в этот mbuf содержание шаблона заголовка. Если данные для отправки помещаются в тот же самый mbuf, что и заголовок, tcpoutput() копирует их на место из буфера отправки сокета, используя процедуру mcopydata(). В противном случае tcpoutput() добавляет данные для отправки в качестве отдельной цепочки mbuf, полученной с помощью операции mcopy() из соответствующей части буфера отправки. Номер последовательности для пакета устанавливается из sndjixt, а подтверждение устанавливается из rcvnxt. Флаги получаются из массива, содержащего флаги, которые должны отправляться в каждом состоянии соединения. Окно для объявления вычисляется из объема оставшегося в приемном буфере сокета пространства; однако, если этого пространства мало (менее одной четверти буфера или менее одного сегмента), оно устанавливается в ноль. Окно никогда не может заканчиваться на номере последовательности меньшем, чем номер, на котором закончился предыдущий пакет. Если были установлены срочные данные, соответствующим образом устанавливаются указатель на срочные данные и флаг.

Должен быть установлен еще один флаг: флаг PUSH-пакета указывает, что данные должны быть переданы пользователю; он подобен запросу очистки буфера. Этот флаг обычно рассматривается как устаревший, но он устанавливается каждый раз, когда были отправлены все данные в буфере отправки; FreeBSD игнорирует этот флаг на вводе. Когда заголовок заполнен, вычисляется контрольная сумма пакета. Оставшиеся части IP-заголовка инициализируются, включая поля типа-службы и времени-жизни, и пакет отправляется с помощью ipoutput(). Таймер повторной передачи запускается, если он еще не работает, а значения sndjixt и sndjnax для соединения обновляются.


Похожие:
Еще по теме:
Советуем прочитать:

Сейчас 60 гостей онлайн

Реклама на сайте:

срочно снять аренда квартир в Москве быстрый поиск

. электролобзики интернет магазин: электролобзики - шуруповерт крафт.

Что выбрать интернет магазины бытовой техники одесса широкий ассортимент.