Шрифт:
Закладка:
Каждый компьютер, поддерживающий TCP, имеет транспортную подсистему TCP, которая является либо библиотечной процедурой, либо пользовательским процессом, либо (чаще всего) частью ядра системы. В любом случае транспортная подсистема управляет TCP-потоками и интерфейсом с IP-уровнем. Она принимает потоки пользовательских данных от локальных процессов, делит их на части, не превышающие 64 Кбайт (на практике это число обычно равно 1460 байтам данных, что позволяет поместить их в один фрейм Ethernet с заголовками IP и TCP), и отправляет их в виде отдельных IP-дейтаграмм. Когда IP-дейтаграммы с TCP-данными приходят на компьютер, они передаются TCP-подсистеме, которая восстанавливает исходный байтовый поток. Для простоты мы иногда будем употреблять «TCP» для обозначения транспортной подсистемы TCP (части программного обеспечения) или протокола TCP (набора правил). Из контекста будет понятно, что имеется в виду. Например, в выражении «Пользователь передает данные TCP» подразумевается, естественно, транспортная подсистема TCP.
Уровень IP не гарантирует правильной доставки дейтаграмм и не накладывает ограничений на скорость их отправки. Именно TCP приходится выбирать правильную скорость отправки (согласно целям эффективного использования пропускной способности и предотвращения перегрузок), следить за истекшими интервалами ожидания и в случае необходимости заниматься повторной передачей дейтаграмм, не достигших адресата. Иногда дейтаграммы доставляются в неправильном порядке. Восстанавливать из них сообщения также обязан TCP. Таким образом, протокол TCP призван обеспечить хорошую производительность и надежность, о которой мечтают многие приложения и которая не предоставляется протоколом IP.
6.5.2. Модель службы TCP
В основе службы TCP лежат сокеты (sockets), создаваемые как отправителем, так и получателем. Они обсуждались в разделе 6.1.3. У каждого сокета есть номер (адрес), состоящий из IP-адреса хоста и 16-битного номера, локального по отношению к хосту и называемого портом. Порт в TCP — это TSAP-адрес. Для обращения к службе TCP между сокетами двух компьютеров должно быть явно установлено соединение. Вызовы сокетов перечислены на илл. 6.5.
Один сокет может использоваться одновременно для нескольких соединений. Другими словами, два и более соединения могут оканчиваться одним сокетом. Соединения различаются по идентификаторам сокетов на обоих концах: (socket1, socket2). Номера виртуальных каналов или другие идентификаторы не используются.
Номера портов со значениями ниже 1024 зарезервированы стандартными службами и доступны только привилегированным пользователям (например, root в UNIX-системах). Они называются известными портами (well-known ports). К примеру, любой процесс, желающий удаленно загрузить почту с хоста, может связаться с портом 143 хоста-адресата и обратиться, таким образом, к его IMAP-демону. Список известных портов приведен на сайте www.iana.org. На данный момент их насчитывается более 700. Некоторые из них перечислены на илл. 6.34.
Порт
Протокол
Использование
20, 21
FTP
Передача файлов
22
SSH
Дистанционный вход в систему, замена Telnet
25
SMTP
Электронная почта
80
HTTP
Всемирная паутина (World Wide Web)
110
POP-3
Удаленный доступ к электронной почте
143
IMAP
Удаленный доступ к электронной почте
443
HTTPS
Защита от угроз (HTPP через SSL/TLS)
543
RTSP
Контроль воспроизведения мультимедиа
631
IPP
Коллективное использование принтера
Илл. 6.34. Некоторые зарезервированные порты
Порты с номерами от 1024 до 49151 можно зарегистрировать через IANA для непривилегированных пользователей, однако приложения могут выбирать свои собственные порты (что они обычно и делают). К примеру, приложение BitTorrent для однорангового совместного доступа к файлам использует (неофициально) порты 6881–6887, но другие порты также возможны.
Конечно, можно было бы еще во время загрузки связать FTP-демон с портом 21, SSH-демон с портом 22 и т.д. Но тогда бы память была забита демонами, которые чаще всего простаивают. Вместо этого обычно используется один демон, называемый в UNIX inetd (Internet daemon). Он связывается с несколькими портами и ожидает первое входящее соединение. Когда оно возникает, inetd создает новый процесс и вызывает подходящий демон для обработки запроса. Таким образом, постоянно активен только inetd, остальные вызываются, только когда для них есть работа. Inetd узнает, какие порты нужно использовать, из конфигурационного файла. Это означает, что системный администратор может настроить систему так, чтобы с самыми загруженными портами (например, 80) были связаны постоянные демоны, а с остальными — inetd.
Все TCP-соединения являются полнодуплексными и двухточечными. «Полнодуплексное» означает, что трафик может следовать одновременно в обе стороны, а «двухточечное» — что у него есть две конечные точки. Широковещание и многоадресная рассылка протоколом TCP не поддерживаются.
TCP-соединение представляет собой байтовый поток, а не поток сообщений. Границы между сообщениями не сохраняются. Например, если отправляющий процесс записывает в TCP-поток четыре 512-байтные порции данных, эти данные могут быть доставлены получающему процессу в виде четырех 512-байтных порций, двух 1024-байтных порций, одной 2048-байтной порции (илл. 6.35) или как-то еще. Способа, с помощью которого получатель мог бы определить, как записывались данные, не существует.
Илл. 6.35. (а) Четыре 512-байтных сегмента, отправленные как отдельные IP-дейтаграммы. (б) 2048 байт данных, доставленные приложению с помощью одного вызова процедуры READ
Файлы в системе UNIX также обладают этим свойством. Программа, читающая файл, не может определить, как был записан этот файл: поблочно, побайтно или целиком. Как и файлы UNIX, TCP-программы не имеют представления о назначении байтов и не интересуются этим. Байт для них — просто байт.
Получив данные от приложения, протокол TCP может отправить их сразу или поместить в буфер (чтобы собрать больше данных и отправить их за один раз) по своему усмотрению. Но иногда приложению необходимо, чтобы данные были переданы немедленно. Допустим, пользователь интерактивной игры хочет отправить поток обновлений. Важно, чтобы они передавались сразу же, а не сохранялись в буфере до появления других обновлений. Для ускорения передачи данных в TCP существует флаг PUSH (толкнуть), который включается в пакеты. Изначально предполагалось, что с его помощью приложения будут сообщать TCP, что не нужно задерживать передачу пакета. Однако приложения не могут сами устанавливать PUSH при отправке данных. Вместо этого в различных операционных системах используются специальные параметры, позволяющие ускорить передачу данных (например, TCP_NONDELAY в Windows и Linux).
Для тех, кто интересуется историей интернета, мы