TCP(7)

НАЗВАНИЕ
tcp - протокол TCP.

ОБЗОР
#include <sys/socket.h>
#include <netinet/in.h>
tcp_socket = socket(PF_INET, SOCK_STREAM, 0);

ОПИСАНИЕ
Это реализация протокола TCP, определенного в RFC793, RFC1122 и RFC2001 с дополнениями NewReno и SACK. Этот протокол предоставляет надежное, потокоориентированное, дуплексное соединение между двумя сокетами поверх ip(7). TCP гарантирует, что данные приходят в правильном порядке и повторно посылает пропавшие пакеты. Он генерирует и проверяет контрольные суммы для каждого пакета, чтобы выявить ошибки пересылки. TCP не сохраняет границы записей. У только что созданного TCP-сокета нет ни удаленного, ни локального адреса: он не полностью определен. Для создания исходящего TCP-соединения с другим TCP-сокетом надо использовать connect(2). Чтобы принимать новые входящие соединения, сначала надо связать сокет с локальным адресом и портом, используя bind(2), а затем вызвать listen(2), чтобы сокет начал "слушать", ожидая соединения. После этого можно принимать входящие соединения с помощью accept(2), создавая при этом новые сокеты. Сокет, который успешно вызвал accept или connect, является полностью определенным и может пересылать данные. Данные не могут пересылаться через сокеты, которые находятся в слушающем состоянии или еще не установили соединение. Linux 2.2 поддерживает дополнения к TCP для обеспечения высокой производительности, которые определены в RFC1323. В список таких дополнений входят большие TCP-окна для поддержки линий с высокой пропускной способностью или большими задержками. Чтобы воспользоваться этим, надо увеличить размеры буферов приема и передачи. Их можно установить глобально с помощью sysctls net.core.wmem_default и net.core.rmem_default, или же для каждого сокета в отдельности, используя опции сокета SO_SNDBUF и SO_RCVBUF. Максимальные размеры буферов сокета ограничены глобальными sysctl-значениями net.core.rmem_max и net.core.wmem_max. Более подробную информацию смотри в socket(7).

TCP поддерживает высокоприоритетные сообщения. Высокоприоритетные сообщения используются, чтобы дать сигнал получателю, что в потоке данных есть некоторое важное сообщение и его нужно обработать как можно скорее. Чтобы послать высокоприоритетное сообщение, надо указать опцию MSG_OOB в send(2). При получении высокоприоритетного сообщения ядро посылает сигнал SIGURG либо читающему процессу, либо процессу или группе процессов, которые были назначены сокету при использовании ioctls FIOCSPGRP или FIOCSETOWN. Если указана опция сокета SO_OOBINLINE, то высокоприоритетное сообщение помещается в обычный поток данных (и его наличие может быть проверено с помощью ioctl SIOCATMARK), в противном случае оно может быть получено только когда для sendmsg(2) установлен флаг MSG_OOB.

ФОРМАТЫ АДРЕСОВ
TCP построен поверх IP (смотри ip(7)). Форматы адресов, определенные в ip(7), применимы к TCP. TCP поддерживает только соединения типа точка-точка; широковещательные и групповые сообщения не поддерживаются.

SYSCTL-ЗНАЧЕНИЯ
Эти sysctl-значения могут быть доступны с помощью файлов /proc/sys/net/ipv4/* или через интерфейс sysctl(2). Кроме того, большинство sysctls IP применимы и к TCP; смотри ip(7).

tcp_window_scaling
    Включает масштабирование TCP-окон, описанное в RFC1323.

tcp_sack
    Включает выборочное подтверждение TCP, описанное в RFC2018.

tcp_timestamps
    Включает TCP timestamps, описанные в RFC1323.

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

tcp_keepalive_probes
    Максимальное количество 'keep-alive'-пакетов TCP, которое будет послано до того как соединение будет считаться разорванным. 'Keep-alive'-пакеты передаются только если опция сокета SO_KEEPALIVE включена.

tcp_keepalive_time
    Сколько секунд должно пройти с момента прекращения передачи данных и до начала посылки 'keep-alive'-пакетов через соединение. По умолчанию это число равно 10800 секундам (3 часам).

tcp_max_ka_probes
    Сколько 'keep-alive'-пакетов будет послано за промежуток slow timer run. Во избежание вспышек количества посылаемых пакетов эта величина должна быть не очень большой.

tcp_stdurg
    Включает строгую интерпретацию поля указателя высокоприоритетности TCP, описанную в RFC793. По умолчанию используется BSD-совместимая интерпретация указателя высокоприоритетности, согласно которой он указывает на первый байт после высокоприоритетных данных. Интерпретация, данная в RFC793, требует, чтобы он указывал на последний байт высокоприоритетных данных. Включение этой опции может привести к проблемам взаимодействия разных систем.

tcp_syncookies
    Включает TCP syncookies. Ядро должно быть скомпилировано с опцией CONFIG_SYN_COOKIES. Syncookies защищают сокет от перегрузки, когда приходит слишком много запросов на создание соединения. Если включить syncookies, клиенты больше не смогут обнаружить перегрузку машины с маленьким тайм-аутом.

tcp_max_syn_backlog
    Длина очереди запросов на установление соединения, для каждого отдельного сокета. Начиная с Linux 2.2, это число, определяемое в listen(2), указывает длину очереди запросов на установление соединения от сокетов, с которыми уже установлен контакт. Максимальная длина очереди сокетов, с которыми соединение еще не установлено (которые находятся в состоянии SYN_RECV ), может быть установлена этим sysctl для каждого отдельного сокета, который находится в состоянии прослушивания. Если запросов на соединение приходит больше, то Linux начинает их отбрасывать. Если включены syncookies, то система продолжает отвечать на запросы, а описываемое ограничение на длину очереди запросов фактически игнорируется.

tcp_retries1
    Определяет сколько раз посылать ответ на запрос установления соединения.

tcp_retries2
    Определяет сколько раз посылать TCP-пакет при уже установленном соединении, до того как соединение будет считаться разорванным.

tcp_syn_retries
    Определяет, сколько раз пытаться послать SYN-запрос для установления соединения с удаленным хостом до того как соединение будет считаться разорванным и сообщено об ошибке. Это число должно быть меньше 255. Этот тайм-аут устанавливается только для исходящих соединений; количество повторных передач для входящих соединений определяется tcp_retries1.

tcp_retrans_collapse
    Пытаться ли посылать полноразмерные сообщения при повторных передачах. Используется, чтобы обойти ошибки в некоторых TCP-стеках.

ОПЦИИ СОКЕТА
Чтобы установить или узнать опцию сокета TCP, надо вызвать getsockopt(2) для получения значения опции или setsockopt(2) для записи опции сокета, который принадлежит семейству SOL_TCP. Кроме того, большинство опций сокета SOL_IP действительны для сокетов TCP. Более подробную информацию смотри в ip(7).

TCP_NODELAY
    Отключает алгоритм Нэгла (Nagle). Это означает, что пакеты всегда отсылаются так часто, как это возможно, без применения дополнительных задержек; расплата за это -- увеличение количества пакетов в сети. Значением может быть ноль или единица.

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

TCP_CORK
    При включении этой опции, перестают отсылаться частичные кадры. Все запрошенные частичные кадры будут отосланы, когда эта опция снова будет отключена. Это полезно для работы с заголовками перед вызовом sendfile(2), или для улучшения пропускной способности. Эта опция не должна использоваться совместно с опцией TCP_NODELAY.

IOCTLS
Эти ioctls могут быть доступны через ioctl(2). Правильный синтаксис:

    int value;
    error = ioctl(tcp_socket, ioctl_type, &value);

FIONREAD или TIOCINQ
    Возвращает количество непрочитанных данных в очереди, находящихся в буфере приема. Аргументом является указатель на тип integer.

SIOCATMARK
    Возвращает истинное значение, если все высокоприоритетные сообщения уже получены пользовательской программой. Используется вместе с SO_OOBINLINE. Аргументом является указатель на тип integer, в который записывается результат.

TIOCOUTQ
    Возвращает количество еще не посланных данных, находящихся в очереди передачи сокета, в переданный указатель на тип integer. К сожалению, реализация этого ioctl ошибочна во всех известных версиях Linux: возвращается размер свободного места в очереди передачи (фактически -- размер буфера минус количество использованных байт, включая метаданные). Это будет исправлено в следующих версиях Linux. Если вы используете TIOCOUTQ, пожалуйста, сделайте проверку на оба варианта поведения, чтобы ваша программа корректно работала в будущих версиях, а также на других Unix'ах.

ОБРАБОТКА ОШИБОК
При возникновении ошибки в сети TCP пытается заново послать пакет. Если спустя некоторое время это не приведет к успеху, то будет сообщено либо о ETIMEDOUT, либо о последней ошибке, полученной в течение этого соединения.

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

ЗАМЕЧАНИЯ
Когда возникает ошибка, приводящая к повторному установлению соединения, сигнал SIGPIPE , возникающий при записи в сокет, посылается только в том случае, если опция SO_KEEPOPEN сокета включена.

У TCP нет настоящих 'out-of-band' (внепотоковых) сообщений: у него есть высокоприоритетные сообщения. В Linux это означает, что если другая сторона присылает новые высокоприоритетные сообщения, то высокоприоритетные сообщения, которые пришли ранее, будут помещены в поток как обычные данные (даже если опция SO_OOBINLINE не установлена). Это отличается от стеков, основанных на BSD.

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

КОДЫ ОШИБОК

EPIPE
    Другая сторона неожиданно закрыла сокет или была выполнена попытка чтения из закрытого сокета.

ETIMEDOUT
    Другая сторона не подтвердила получение посланных данных спустя некоторое время.

EAFNOTSUPPORT
    У передающего сокета тип адреса, который задается в sin_family, не совпадает с AF_INET.

Все коды ошибок, определенные для ip(7) или для сокетов этого семейства также могут быть возвращены для TCP.

ОШИБКИ РЕАЛИЗАЦИИ
Описаны не все коды ошибок.

Не описан IPv6.

Не описаны опции прозрачного прокси.

ВЕРСИИ
Sysctls появились в Linux 2.2. IP_RECVERR является новой особенностью в Linux 2.2. Опция TCP_CORK появилась в 2.2.

СМОТРИ ТАКЖЕ
socket(7), socket(2), ip(7), sendmsg(2), recvmsg(2)
RFC793, где описана спецификация TCP.
RFC1122, где описаны требования TCP и описание алгоритма Нэгла (Nagle).
RFC2581, где описаны некоторые алгоритмы TCP.

ПЕРЕВОД
Copyright (C) Антон Аюпов <astray@yandex.ru> 2000