getsockopt()

Получить параметры, связанные с сокетом

Прототип:

#include <sys/types.h>
#include <sys/socket.h>
int getsockopt( int s,
int level,
int optname,
void *optval,
socklen_t *optlen );

Аргументы:

s
Файловый дескриптор сокета, к которому должна быть применена опция, возвращаемый функцией socket().
level
Уровень протокола, к которому должна применяться опция. В большинстве случаев это уровень сокета, который указывается как SOL_SOCKET.
optname
Параметр для дескриптора файла сокета. Список параметров см. в разделе «Параметры» ниже.
optval
Указатель на значение опции (в большинстве случаев независимо от того, должна ли опция быть включена или выключена). Если значение параметра не должно возвращаться, optval может иметь значение NULL.

Большинство параметров уровня сокета используют параметр int для optval. Другие опции, такие как SO_LINGER, SO_SNDTIMEO, и SO_RCVTIMEO, используют структуры, которые также позволяют получить данные, связанные с опцией.
optlen
Указатель на длину значения опции. Этот аргумент является параметром типа "значение-результат"; инициализируйте его, чтобы указать размер буфера, на который указывает optval.

Библиотека:

libsocket

Описание:

Функция getsockopt() получает опции, связанные с сокетом.

Работа с опциями сокета

Для работы с опцией сокета необходимо указать имя опции (optname) и уровень (level), на котором находится опция.

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


Note: Последние два способа могут не работать с пользовательской конфигурацией /etc/protocols.

Параметр optname и любые указанные параметры передаются без интерпретации в соответствующий модуль протокола для интерпретации. Заголовочный файл <sys/socket.h> содержит определения параметров уровня сокета. Опции на других уровнях протокола различаются по формату и имени.


Note: Поскольку уровни (например, SOL_SOCKET, IPPROTO_IP и IPPROTO_TCP) и параметры внутри уровней могут различаться, необходимо убедиться, что для них обоих подключены правильные заголовочные файлы. Например, при установке TCP_NODELAY:

int on = 1;
setsockopt( s, IPPROTO_TCP, TCP_NODELAY, &on, sizeof( on ) );

уровень IPPROTO_TCP определен в <netinet/in.h>, в то время как TCP_NODELAY определен в <netinet/tcp.h>.


Опции

В этом разделе описаны некоторые из наиболее распространенных параметров и соответствующий им level.

Несколько ссылок для поиска:

Группа опций IPPROTO_IP:
IP_HDRINCL
IP_TOS

Группа опций SOL_SOCKET:
SO_BINDTODEVICE
SO_BROADCAST
SO_DEBUG
SO_DONTROUTE
SO_ERROR
SO_KEEPALIVE
SO_LINGER
SO_OOBINLINE
SO_RCVBUF и SO_SNDBUF
SO_RCVLOWAT
SO_RCVTIMEO
SO_REUSEADDR
SO_REUSEPORT
SO_SNDLOWAT
SO_SNDTIMEO
SO_TIMESTAMP
SO_TYPE
SO_USELOOPBACK

Группа опций IPPROTO_TCP:
TCP_KEEPALIVE
TCP_NODELAY


Note: Если не указано иное, можно проверить состояние параметра, вызвав getsockopt(), и установить состояние, вызвав setsockopt().

Группа опций IPPROTO_IP

IP_HDRINCL

уровень: IPPROTO_IP

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

socket( AF_INET, SOCK_RAW, ... )

IP_TOS

уровень: IPPROTO_IP

Получает или устанавливает поле типа обслуживания в IP-заголовке для сокетов SOCK_STREAM и SOCK_DGRAM.

Группа опций SOL_SOCKET

SO_BINDTODEVICE

уровень: SOL_SOCKET

Применимо только к setsockopt().

Разрешает отправку или получение пакетов только на указанном интерфейсе. Если указанный интерфейс конфликтует с параметрами bind() или с таблицей маршрутизации, может возникнуть ошибка или нежелательное поведение.

Данная опция принимает структуру ifreq, включающую поле ifr_name, содержащую имя интерфейса (например, en0). В настоящее время можно использовать эту опцию только для сокетов UDP.

SO_BROADCAST

уровень: SOL_SOCKET

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

socket( AF_INET, SOCK_DGRAM, ... )

«Трансляция» была привилегированной операцией в более ранних версиях системы.

SO_DEBUG

уровень: SOL_SOCKET

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

SO_DONTROUTE

уровень: SOL_SOCKET

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

SO_ERROR

уровень: SOL_SOCKET

Применимо только к setsockopt().

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

SO_KEEPALIVE

уровень: SOL_SOCKET

Включает или отключает периодическую (не реже, чем каждые 2 часа) передачу сообщений по подключенному сокету. Если подключенная сторона не отвечает на эти сообщения, соединение считается разорванным, и процессы, использующие сокет, уведомляются с помощью сигнала SIGPIPE, когда они пытаются отправить данные. См. «Время поддержки активности» ниже.

SO_LINGER

уровень: SOL_SOCKET

Управляет действием, предпринимаемым, когда неотправленные сообщения помещаются в очередь в сокет при выполнении close().

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

Если отключен, система обрабатывает close() таким образом, чтобы позволить процессу продолжиться как можно скорее.

Структура linger (определена в <sys/socket.h>) указывает желаемое состояние параметра в поле l_onoff и интервал задержки в поле l_linger в секундах. Значение 0 вызывает сброс сокета, когда приложение закрывает сокет.

SO_OOBINLINE

уровень: SOL_SOCKET

Для протоколов, поддерживающих внеполосные данные, разрешает или запрещает размещение внеполосных данных в обычную очередь ввода данных в том виде, в каком они были получены. Данные доступны с помощью вызовов recv() или read() без флага MSG_OOB. Некоторые протоколы всегда имеют поведение, как если бы эта опция была установлена.

SO_RCVBUF и SO_SNDBUF

уровень: SOL_SOCKET

Получает или задает обычные размеры буфера, выделенные для буферов вывода (SO_SNDBUF) и ввода (SO_RCVBUF). Можно увеличить размер буфера для соединений большого объема или уменьшить его, чтобы ограничить возможное отставание входящих данных. Система устанавливает абсолютный предел для этих значений и по умолчанию устанавливает их не менее 16 КБ для сокетов TCP.

SO_RCVLOWAT

уровень: SOL_SOCKET

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

При установке значения больше, чем значение по умолчанию, блокировка входящих вызовов будет ожидать, пока вызовы не получат значение low-water или запрошенное количество, в зависимости от того, что меньше. Вызовы приема могут по-прежнему возвращать значение меньше, чем low-water, в случаях если: возникла ошибка; сигнал перехвачен или если тип данных, следующих в очереди приема, отличается от возвращаемого.

SO_RCVTIMEO

уровень: SOL_SOCKET

Получает или задает значение тайм-аута для операций ввода. Принимает параметр struct timeval (определенный в <sys/time.h>) с количеством секунд и микросекунд, используемых для ограничения ожидания завершения операций ввода.

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

SO_REUSEADDR

уровень: SOL_SOCKET

Включает или отключает повторное использование дублирующихся адресов и привязок портов. Указывает, что правила, используемые при проверке адресов, предоставленных в вызове bind(), разрешают/запрещают повторное использование локальных адресов.

SO_REUSEPORT

уровень: SOL_SOCKET

Включает или отключает повторяющиеся привязки адресов и портов. Полные повторяющиеся привязки несколькими процессами разрешены, если все они устанавливают SO_REUSEPORT перед привязкой порта. Этот параметр позволяет нескольким экземплярам программы получать многоадресные или широковещательные датаграммы UDP/IP, предназначенные для привязанного порта. См. параметр reuseport_unicast в io-pkt-* чтобы увидеть, как одноадресные пакеты также принимаются на всех сокетах, привязанных к одному и тому же порту.

SO_SNDLOWAT

уровень: SOL_SOCKET

Получает или задает минимальное количество операций вывода. В BSD это значение обычно равно 2048, но это вычисленное значение в ЗОСРВ «Нейтрино». Если требуется конкретный SO_SNDLOWAT, необходимо указать это количество операций. Большинство операций вывода обрабатывают все данные, предоставленные вызовом, доставляя данные в протокол для передачи и блокировки по мере необходимости для управления потоком. Операции неблокирующего вывода будут обрабатывать столько данных, сколько разрешено (при условии управления потоком без блокировки), но не будут обрабатывать никаких данных, если управление потоком не позволяет обрабатывать меньшее из минимального значения метки или всего запроса.

Операция select(), которая проверяет возможность записи в сокет, возвращает true только в том случае, если low-water операций может быть обработано.

SO_SNDTIMEO

уровень: SOL_SOCKET

Получает или задает значение тайм-аута для операций вывода. Принимает параметр struct timeval (определенный в <sys/time.h>), который включает в себя количество секунд и микросекунд, которые используются для ограничения ожидания завершения операций вывода. Если операция отправки заблокирована на это время, то она возвращается с частичным подсчетом времени или с ошибкой EWOULDBLOCK, если данные не были отправлены.

Данный таймер перезапускается каждый раз, когда в протокол доставляются дополнительные данные, подразумевая, что ограничение применяется к выходным частям данных, размер которых варьируется от low-water до high-water для вывода. Тайм-ауты ограничены 32 секундами, но могут быть и меньше.

SO_TIMESTAMP

уровень: SOL_SOCKET

Включает или отключает прием метки времени с датаграммами. Если включен для сокета SOCK_DGRAM, вызов recvmsg() возвращает метку времени, соответствующую времени получения датаграммы. Поле msg_control в структуре msghdr указывает на буфер, который содержит структуру cmsghdr, за которой следует struct timeval. Поля cmsghdr имеют следующие значения:

cmsg_len = sizeof( struct cmsghdr ) + sizeof( struct timeval )
cmsg_level = SOL_SOCKET
cmsg_type = SCM_TIMESTAMP

SO_TYPE

уровень: SOL_SOCKET

Применимо только к getsockopt().

Получает тип сокета (например, SOCK_STREAM). Эта информация полезна для серверов, которые наследуют сокеты при запуске.

SO_USELOOPBACK

уровень: SOL_SOCKET

Разрешает или запрещает отправляющему процессу получать свои собственные сообщения маршрутизации.

Группа опций IPPROTO_TCP

TCP_KEEPALIVE

уровень: IPPROTO_TCP

Возвращает или задает интервал времени в секундах между проверками активности (значение по умолчанию 2 часа). Принимает параметр struct timeval с числом секунд ожидания между проверками активности. См. «Время поддержки активности» ниже.

TCP_NODELAY

уровень: IPPROTO_TCP

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


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

Время активности

Используйте опцию SO_KEEPALIVE чтобы включить проверки активности, а опцию TCP_KEEPALIVE чтобы установить время ожидания перед отправкой следующих данных (по умолчанию 7200 секунд или два часа).

Можно установить количество проверок для отправки и интервал между проверками с помощью функции sysctl(), которая изменяет или запрашивает состояние диспетчера сокетов. Документация по утилите sysctl включает информацию об идентификаторах, связанных с keepcnt и keepintvl. По умолчанию количество неудачных проверок перед тем, как сокет будет считаться неисправным, равно 8, а интервал между проверками по умолчанию равен 75 секундам.

Пример включения поддержки активности сокета с периодом простоя 20 секунд, и затем осуществления до 3 попыток с интервалом в 5 секунд:

int mib[4];
int on=1, ival;
struct timeval tval;
mib[0] = CTL_NET;
mib[1] = AF_INET;
mib[2] = IPPROTO_TCP;
mib[3] = TCPCTL_KEEPCNT;
ival = 3; /* Number of keepalive probe attempts (default is 8) */
sysctl( mib, 4, NULL, NULL, &ival, sizeof( ival ) );
mib[0] = CTL_NET;
mib[1] = AF_INET;
mib[2] = IPPROTO_TCP;
mib[3] = TCPCTL_KEEPINTVL;
ival = 10; /* Half seconds between probe attempts; default is 150 (75 sec) */
sysctl( mib, 4, NULL, NULL, &ival, sizeof( ival ) );
memset( &tval, sizeof( tval ), 0 );
tval.tv_sec = 20; /* Seconds of idle time before probing starts (default is 7200) */
setsockopt( fdi, SOL_SOCKET, SO_KEEPALIVE, (void *)&on, sizeof( on ) );
setsockopt( fdi, IPPROTO_TCP, TCP_KEEPALIVE, (void *)&tval, sizeof( tval ) );


Note: Необходимо помнить, что приведенные выше вызовы sysctl() вносят общесистемные изменения, которые сохраняются после завершения процесса.

Возвращаемое значение:

0
Успешное завершение.
-1
Возникла ошибка. Код ошибки записан в errno.

Коды ошибок:

EBADF
Некорректный файловый дескриптор s.
EDOM
Значение вне допустимого диапазона.
EFAULT
Адрес, на который указывает optval, не находится в допустимой части адресного пространства процесса. Для getsockopt() эта ошибка также может быть возвращена, если optlen не находится в допустимой части адресного пространства процесса.
EINVAL
Аргумент optval не может быть NULL; optlen не может быть 0.
ENOPROTOOPT
Опция неизвестна на указанном уровне.

Классификация:

POSIX 1003.1

Безопасность использования
Точка остановки потока
Да
Обработчик прерываний
Нет
Обработчик сигналов
Нет
В потоке
Да

Тематические ссылки:

ICMP, IP, TCP, и UDP протоколы

close(), getprotobyname(), ioctl(), read(), select(), setsockopt(), socket(), sysctl()

/etc/protocols, sysctl в Справочнике по Утилитам




Предыдущий раздел: Описание API сетевой библиотеки