Spec-Zone.ru › Perl 5.28

Сокет

СОДЕРЖАНИЕ

  • НАЗВАНИЕ
  • СИНТАКСИС
  • ОПИСАНИЕ
  • КОНСТАНТЫ
    • PF_INET, PF_INET6, PF_UNIX, ...
    • AF_INET, AF_INET6, AF_UNIX, ...
    • SOCK_STREAM, SOCK_DGRAM, SOCK_RAW, ...
    • SOCK_NONBLOCK. SOCK_CLOEXEC
    • SOL_SOCKET
    • SO_ACCEPTCONN, SO_BROADCAST, SO_ERROR, ...
    • IP_OPTIONS, IP_TOS, IP_TTL, ...
    • IP_PMTUDISC_WANT, IP_PMTUDISC_DONT, ...
    • IPTOS_LOWDELAY, IPTOS_THROUGHPUT, IPTOS_RELIABILITY, ...
    • MSG_BCAST, MSG_OOB, MSG_TRUNC, ...
    • SHUT_RD, SHUT_RDWR, SHUT_WR
    • INADDR_ANY, INADDR_BROADCAST, INADDR_LOOPBACK, INADDR_NONE
    • IPPROTO_IP, IPPROTO_IPV6, IPPROTO_TCP, ...
    • TCP_CORK, TCP_KEEPALIVE, TCP_NODELAY, ...
    • IN6ADDR_ANY, IN6ADDR_LOOPBACK
    • IPV6_ADD_MEMBERSHIP, IPV6_MTU, IPV6_V6ONLY, ...
  • ОПЕРАЦИИ С СТРУКТУРАМИ
    • $family = sockaddr_family $sockaddr
    • $sockaddr = pack_sockaddr_in $port, $ip_address
    • ($port, $ip_address) = unpack_sockaddr_in $sockaddr
    • $sockaddr = sockaddr_in $port, $ip_address
    • ($port, $ip_address) = sockaddr_in $sockaddr
    • $sockaddr = pack_sockaddr_in6 $port, $ip6_address, [$scope_id, [$flowinfo]]
    • ($port, $ip6_address, $scope_id, $flowinfo) = unpack_sockaddr_in6 $sockaddr
    • $sockaddr = sockaddr_in6 $port, $ip6_address, [$scope_id, [$flowinfo]]
    • ($port, $ip6_address, $scope_id, $flowinfo) = sockaddr_in6 $sockaddr
    • $sockaddr = pack_sockaddr_un $path
    • ($path) = unpack_sockaddr_un $sockaddr
    • $sockaddr = sockaddr_un $path
    • ($path) = sockaddr_un $sockaddr
    • $ip_mreq = pack_ip_mreq $multiaddr, $interface
    • ($multiaddr, $interface) = unpack_ip_mreq $ip_mreq
    • $ip_mreq_source = pack_ip_mreq_source $multiaddr, $source, $interface
    • ($multiaddr, $source, $interface) = unpack_ip_mreq_source $ip_mreq
    • $ipv6_mreq = pack_ipv6_mreq $multiaddr6, $ifindex
    • ($multiaddr6, $ifindex) = unpack_ipv6_mreq $ipv6_mreq
  • ФУНКЦИИ
    • $ip_address = inet_aton $string
    • $string = inet_ntoa $ip_address
    • $address = inet_pton $family, $string
    • $string = inet_ntop $family, $address
    • ($err, @result) = getaddrinfo $host, $service, [$hints]
    • ($err, $hostname, $servicename) = getnameinfo $sockaddr, [$flags, [$xflags]]
  • КОНСТАНТЫ ОШИБОК getaddrinfo() / getnameinfo()
  • ПРИМЕРЫ
    • Поиск для connect()
    • Преобразование адреса в удобочитаемый вид
    • Разрешение имён хостов в IP-адреса
    • Доступ к параметрам сокета
  • АВТОР

НАЗВАНИЕ

Socket - сетевые константы и вспомогательные функции

СИНТАКСИС

Socket модуль низкого уровня, используемый, среди прочего, семейством модулей IO::Socket. Следующие примеры демонстрируют некоторые низкоуровневые использования, но практическая программа, скорее всего, будет использовать API более высокого уровня, предоставляемый IO::Socket или аналогичным.

use Socket qw(PF_INET SOCK_STREAM pack_sockaddr_in inet_aton);

socket(my $socket, PF_INET, SOCK_STREAM, 0)
    or die "socket: $!";

my $port = getservbyname "echo", "tcp";
connect($socket, pack_sockaddr_in($port, inet_aton("localhost")))
    or die "connect: $!";

print $socket "Hello, world!\n";
print <$socket>;

См. также раздел "ПРИМЕРЫ".

ОПИСАНИЕ

Этот модуль предоставляет различные константы, манипуляторы структур и другие функции, относящиеся к сетевому взаимодействию через сокеты. Предоставляемые значения и функции полезны при использовании совместно с функциями ядра Perl, такими как socket(), setsockopt() и bind(). Он также предоставляет несколько других вспомогательных функций, в основном для преобразования сетевых адресов между удобочитаемым и внутренним двоичным форматами, и для операций разрешения имён хостов.

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

Также предоставляются некоторые распространённые константы «перевода строки» для сокетов: константы CR, LF, и CRLF, а также $CR, $LF, и $CRLF, которые соответствуют \015, \012, и \015\012. Если вы не хотите использовать буквальные символы в своих программах, то используйте предоставляемые здесь константы. Они не экспортируются по умолчанию, но могут быть импортированы индивидуально и с меткой экспорта :crlf.

use Socket qw(:DEFAULT :crlf);

$sock->print("GET / HTTP/1.0$CRLF");

Весь подсистему getaddrinfo() можно экспортировать с помощью метки :addrinfo; это экспортирует функции getaddrinfo() и getnameinfo(), а также все константы AI_*, NI_*, NIx_* и EAI_*.

КОНСТАНТЫ

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

PF_INET, PF_INET6, PF_UNIX, ...

Константы семейства протоколов для использования в качестве первого аргумента к socket() или значения параметра сокета SO_DOMAIN или SO_FAMILY.

AF_INET, AF_INET6, AF_UNIX, ...

Константы семейства адресов, используемые структурами адресов сокетов, для передачи таким функциям, как inet_pton() или getaddrinfo(), или возвращаются такими функциями, как sockaddr_family().

SOCK_STREAM, SOCK_DGRAM, SOCK_RAW, ...

Константы типа сокета для использования в качестве второго аргумента к socket() или значения параметра сокета SO_TYPE.

SOCK_NONBLOCK. SOCK_CLOEXEC

Конкретные для Linux сокращения для указания флагов O_NONBLOCK и FD_CLOEXEC во время вызова socket(2).

socket( my $sockh, PF_INET, SOCK_DGRAM|SOCK_NONBLOCK, 0 )

SOL_SOCKET

Константа уровня параметра сокета для setsockopt() и getsockopt().

SO_ACCEPTCONN, SO_BROADCAST, SO_ERROR, ...

Константы имени параметра сокета для setsockopt() и getsockopt() на уровне SOL_SOCKET.

IP_OPTIONS, IP_TOS, IP_TTL, ...

Константы имени параметра сокета для параметров сокета IPv4 на уровне IPPROTO_IP.

IP_PMTUDISC_WANT, IP_PMTUDISC_DONT, ...

Константы значений параметров сокета для параметра сокета IP_MTU_DISCOVER.

IPTOS_LOWDELAY, IPTOS_THROUGHPUT, IPTOS_RELIABILITY, ...

Постоянные значения опций сокета для опции сокета IP_TOS.

MSG_BCAST, MSG_OOB, MSG_TRUNC, ...

Постоянные значения флагов сообщений для send() и recv().

SHUT_RD, SHUT_RDWR, SHUT_WR

Постоянные значения направления для shutdown().

INADDR_ANY, INADDR_BROADCAST, INADDR_LOOPBACK, INADDR_NONE

Постоянные, задающие специальные AF_INET адреса для маскирования, широковещательной рассылки, локального цикла и недействительных адресов.

Обычно эквивалентны inet_aton('0.0.0.0'), inet_aton('255.255.255.255'), inet_aton('localhost') и inet_aton('255.255.255.255') соответственно.

IPPROTO_IP, IPPROTO_IPV6, IPPROTO_TCP, ...

Постоянные значения IP-протокола, используемые в качестве третьего аргумента socket(), аргумента уровня getsockopt() или setsockopt(), или значения опции сокета SO_PROTOCOL.

TCP_CORK, TCP_KEEPALIVE, TCP_NODELAY, ...

Постоянные имена опций сокета для опций сокета TCP на уровне IPPROTO_TCP.

IN6ADDR_ANY, IN6ADDR_LOOPBACK

Постоянные, задающие специальные AF_INET6 адреса для маскирования и локального цикла.

Обычно эквивалентны inet_pton(AF_INET6, "::") и inet_pton(AF_INET6, "::1") соответственно.

IPV6_ADD_MEMBERSHIP, IPV6_MTU, IPV6_V6ONLY, ...

Постоянные имена опций сокета для опций сокета IPv6 на уровне IPPROTO_IPV6.

ОПЕРАЦИИ С СТРУКТУРАМИ

Следующие функции преобразуют списки значений Perl в упакованные двоичные строки, представляющие структуры.

$family = sockaddr_family $sockaddr

Принимает упакованный адрес сокета (как возвращаемый pack_sockaddr_in(), pack_sockaddr_un() или встроенными функциями perl getsockname() и getpeername()). Возвращает тег семейства адресов. Это будет одно из AF_* постоянных значений, таких как AF_INET для sockaddr_in адресов или AF_UNIX для sockaddr_un. Его можно использовать для определения того, какой unpack использовать для sockaddr неизвестного типа.

$sockaddr = pack_sockaddr_in $port, $ip_address

Принимает два аргумента: номер порта и строку-объект (как возвращаемое inet_aton() или v-строку). Возвращает sockaddr_in структуру с упакованными аргументами и заполненными AF_INET. Для сокетов доменной сети эта структура обычно необходима в качестве аргументов в bind(), connect() и send().

Неопределенный аргумент $port принимается как ноль; неопределенный аргумент $ip_address считается ошибкой.

($port, $ip_address) = unpack_sockaddr_in $sockaddr

Принимает sockaddr_in структуру (как возвращаемую pack_sockaddr_in(), getpeername() или recv()). Возвращает список из двух элементов: порта и строки-объекта, представляющей IP-адрес (можно использовать inet_ntoa() для преобразования адреса в четырехточечный числовой формат). Вызовет ошибку, если структура не представляет AF_INET адрес.

В скалярном контексте возвращает только IP-адрес.

$sockaddr = sockaddr_in $port, $ip_address

($port, $ip_address) = sockaddr_in $sockaddr

Обёртка pack_sockaddr_in() или unpack_sockaddr_in(). В контексте списка распаковывает свой аргумент и возвращает список, состоящий из порта и IP-адреса. В скалярном контексте упаковывает свои аргументы порта и IP-адреса как sockaddr_in и возвращает его.

В основном предоставляется для обеспечения обратной совместимости; лучше явно использовать pack_sockaddr_in() или unpack_sockaddr_in().

$sockaddr = pack_sockaddr_in6 $port, $ip6_address, [$scope_id, [$flowinfo]]

Принимает от двух до четырёх аргументов: номер порта, строку-объект (как возвращаемое inet_pton()), необязательно номер идентификатора области, необязательно номер метки потока. Возвращает sockaddr_in6 структуру с упакованными аргументами и заполненными AF_INET6. IPv6-эквивалент pack_sockaddr_in().

Неопределённый аргумент $port принимается как ноль; неопределённый аргумент $ip6_address считается ошибкой.

($port, $ip6_address, $scope_id, $flowinfo) = unpack_sockaddr_in6 $sockaddr

Принимает sockaddr_in6 структуру. Возвращает список из четырёх элементов: номер порта, строку-объект, представляющую IPv6-адрес, идентификатор области и метку потока. (Можно использовать inet_ntop() для преобразования адреса в обычный строковый формат). Вызовет ошибку, если структура не представляет AF_INET6 адрес.

В скалярном контексте возвращает только IP-адрес.

$sockaddr = sockaddr_in6 $port, $ip6_address, [$scope_id, [$flowinfo]]

($port, $ip6_address, $scope_id, $flowinfo) = sockaddr_in6 $sockaddr

Обёртка pack_sockaddr_in6() или unpack_sockaddr_in6(). В контексте списка распаковывает свой аргумент согласно unpack_sockaddr_in6(). В скалярном контексте упаковывает свои аргументы согласно pack_sockaddr_in6().

В основном предоставляется для обеспечения обратной совместимости; лучше явно использовать pack_sockaddr_in6() или unpack_sockaddr_in6().

$sockaddr = pack_sockaddr_un $path

Принимает один аргумент, имя пути. Возвращает sockaddr_un структуру с упакованным путём и заполненными AF_UNIX. Для PF_UNIX сокетов эта структура обычно необходима в качестве аргументов в bind(), connect() и send().

($path) = unpack_sockaddr_un $sockaddr

Принимает sockaddr_un структуру (как возвращаемую pack_sockaddr_un(), getpeername() или recv()). Возвращает список из одного элемента: имени пути. Вызовет ошибку, если структура не представляет AF_UNIX адрес.

$sockaddr = sockaddr_un $path

($path) = sockaddr_un $sockaddr

Обёртка pack_sockaddr_un() или unpack_sockaddr_un(). В контексте списка распаковывает свой аргумент и возвращает список, состоящий из имени пути. В скалярном контексте упаковывает своё имя пути как sockaddr_un и возвращает его.

В основном предоставляется для обеспечения обратной совместимости; лучше явно использовать pack_sockaddr_un() или unpack_sockaddr_un().

Поддерживаются только если на вашей системе есть <sys/un.h>.

$ip_mreq = pack_ip_mreq $multiaddr, $interface

Принимает IPv4-мультиадрес и, необязательно, адрес интерфейса (или INADDR_ANY). Возвращает ip_mreq структуру с упакованными аргументами. Подходит для использования с IP_ADD_MEMBERSHIP и IP_DROP_MEMBERSHIP sockopts.

($multiaddr, $interface) = unpack_ip_mreq $ip_mreq

Принимает ip_mreq структуру. Возвращает список из двух элементов: IPv4-мультиадрес и адрес интерфейса.

$ip_mreq_source = pack_ip_mreq_source $multiaddr, $source, $interface

Принимает IPv4-мультиадрес, адрес источника и, необязательно, адрес интерфейса (или INADDR_ANY). Возвращает ip_mreq_source структуру с упакованными аргументами. Подходит для использования с IP_ADD_SOURCE_MEMBERSHIP и IP_DROP_SOURCE_MEMBERSHIP sockopts.

($multiaddr, $source, $interface) = unpack_ip_mreq_source $ip_mreq

Принимает ip_mreq_source структуру. Возвращает список из трёх элементов: IPv4-мультиадрес, адрес источника и адрес интерфейса.

$ipv6_mreq = pack_ipv6_mreq $multiaddr6, $ifindex

Принимает IPv6-мультиадрес и номер интерфейса. Возвращает ipv6_mreq структуру с упакованными аргументами. Подходит для использования с IPV6_ADD_MEMBERSHIP и IPV6_DROP_MEMBERSHIP sockopts.

($multiaddr6, $ifindex) = unpack_ipv6_mreq $ipv6_mreq

Принимает ipv6_mreq структуру. Возвращает список из двух элементов: IPv6-адрес и номер интерфейса.

ФУНКЦИИ

$ip_address = inet_aton $string

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

Для обеспечения переносимости не предполагайте, что результат inet_aton() имеет ширину 32 бита, другими словами, что он содержит только IPv4-адрес в сетевом порядке.

Эта функция, предназначенная только для IPv4, предоставляется в основном по причинам обратной совместимости. В новых кодах следует использовать getaddrinfo() или inet_pton() для поддержки IPv6.

$string = inet_ntoa $ip_address

Принимает упакованную двоичную структуру адреса, например, возвращаемую unpack_sockaddr_in() (или v-строку, представляющую четыре октета IPv4-адреса в сетевом порядке), и преобразует её в строку вида d.d.d.d, где d - числа меньше 256 (обычный человекочитаемый четырехточечный числовой формат для адресов Интернета).

Эта функция, предназначенная только для IPv4, предоставляется в основном по причинам обратной совместимости. В новых кодах следует использовать getnameinfo() или inet_ntop() для поддержки IPv6.

$address = inet_pton $family, $string

Принимает семейство адресов (например, AF_INET или AF_INET6) и строку, содержащую текстовое представление адреса в этом семействе, и преобразует её в упакованную двоичную структуру адреса.

См. также getaddrinfo() для более мощной и гибкой функции для поиска адресов сокетов по именам хостов или текстовым адресам.

$string = inet_ntop $family, $address

Принимает семейство адресов и упакованную двоичную структуру адреса и преобразует её в удобочитаемое текстовое представление адреса; обычно в формате d.d.d.d для AF_INET или в формате hhhh:hhhh::hhhh для AF_INET6.

См. также getnameinfo() для более мощной и гибкой функции для преобразования адресов сокетов в удобочитаемые текстовые представления.

($err, @result) = getaddrinfo $host, $service, [$hints]

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

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

Если задано только имя службы, эта функция пытается разрешить его в протокол и номер порта, а затем возвращает список структур адресов, которые представляют его, пригодные для связывания с помощью функции bind(). Это использование должно быть комбинировано с флагом AI_PASSIVE; см. ниже.

Если не задано ни имя, ни имя службы, генерируется ошибка.

Если присутствует, $hints должен ссылаться на хеш, где распознаются следующие ключи:

flags => INT

Битовая маска, содержащая AI_* константы; см. ниже.

family => INT

Ограничить получение только адресов в этой адресной семье

socktype => INT

Ограничить получение только адресов данного типа сокета

protocol => INT

Ограничить получение только адресов для данного протокола

Результат будет списком; первым элементом будет индикатор ошибки, а далее — список структур адресов (если ошибка не произошла).

Значение ошибки будет двойным значением; сравнимым с EAI_* константами ошибок или отображаемым как удобочитаемое сообщение об ошибке. Если ошибка не произошла, значение будет равно нулю и пустой строкой.

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

family => INT

Семейство адресов (например, AF_INET)

socktype => INT

Тип сокета (например, SOCK_STREAM)

protocol => INT

Протокол (например, IPPROTO_TCP)

addr => STRING

Адрес в упакованной строке (например, такой, как возвращается функцией pack_sockaddr_in())

canonname => STRING

Каноническое имя хоста, если был предоставлен AI_CANONNAME флаг, или undef в противном случае. Это поле будет присутствовать только в первом возвращаемом адресе.

В хеше $hints распознаются следующие флаги-константы. Другие константы флагов могут существовать, предоставляемые ОС.

AI_PASSIVE

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

AI_CANONNAME

Указывает, что вызывающий процесс хочет, чтобы поле канонического имени хоста (canonname) результата было заполнено.

AI_NUMERICHOST

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

($err, $hostname, $servicename) = getnameinfo $sockaddr, [$flags, [$xflags]]

Принимая упакованный адрес сокета (например, из getsockname(), getpeername() или возвращаемый getaddrinfo() в addr поле), возвращает имя хоста и символическое имя службы, которые он представляет. $flags может быть битовой маской NI_* констант или по умолчанию равен 0, если не указано.

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

Значение ошибки будет двойным значением; сравнимым с EAI_* константами ошибок или отображаемым как удобочитаемое сообщение об ошибке. Имена хоста и службы будут обычными строками.

Следующие флаги-константы распознаются как $flags. Другие константы флагов могут существовать, предоставляемые ОС.

NI_NUMERICHOST

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

NI_NUMERICSERV

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

NI_NAMEREQD

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

NI_DGRAM

Указывает, что адрес сокета относится к SOCK_DGRAM сокету, для служб, чьё имя различается между протоколами TCP и UDP.

Следующие константы могут быть переданы как $xflags.

NIx_NOHOST

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

NIx_NOSERV

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

getaddrinfo() / getnameinfo() константы ошибок

Следующие константы могут быть возвращены функциями getaddrinfo() или getnameinfo(). Другие могут быть предоставлены ОС.

EAI_AGAIN

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

EAI_BADFLAGS

Значение flags подсказки для getaddrinfo() или параметр $flags для getnameinfo() содержит неизвестные флаги.

EAI_FAMILY

family подсказка для getaddrinfo() или семейство адреса сокета, переданного в getnameinfo(), не поддерживается.

EAI_NODATA

Переданное имя хоста функции getaddrinfo() не предоставило никаких полезных данных адреса.

EAI_NONAME

Переданное имя хоста функции getaddrinfo() не существует, или переданный адрес функции getnameinfo() не связан с именем хоста, и NI_NAMEREQD флаг был передан.

EAI_SERVICE

Имя службы, переданное функции getaddrinfo(), недоступно для заданного типа сокета в $hints.

ПРИМЕРЫ

Поиск для connect()

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

use IO::Socket;
use Socket qw(SOCK_STREAM getaddrinfo);

my %hints = (socktype => SOCK_STREAM);
my ($err, @res) = getaddrinfo("localhost", "echo", \%hints);
die "Cannot getaddrinfo - $err" if $err;

my $sock;

foreach my $ai (@res) {
    my $candidate = IO::Socket->new();

    $candidate->socket($ai->{family}, $ai->{socktype}, $ai->{protocol})
        or next;

    $candidate->connect($ai->{addr})
        or next;

    $sock = $candidate;
    last;
}

die "Cannot connect to localhost:echo" unless $sock;

$sock->print("Hello, world!\n");
print <$sock>;

Поскольку возвращается список потенциальных кандидатов, цикл while пытается подключиться к каждому по очереди, пока не найдёт тот, который успешно пройдёт вызовы socket() и connect().

Эта функция выполняет работу устаревших функций gethostbyname(), getservbyname(), inet_aton() и pack_sockaddr_in().

На практике эту логику лучше реализовывать с помощью IO::Socket::IP.

Преобразование адреса в удобочитаемую строку

Функция getnameinfo() преобразует адрес сокета, например, возвращаемый getsockname() или getpeername(), в пару удобочитаемых строк, представляющих адрес и имя службы.

use IO::Socket::IP;
use Socket qw(getnameinfo);

my $server = IO::Socket::IP->new(LocalPort => 12345, Listen => 1) or
    die "Cannot listen - $@";

my $socket = $server->accept or die "accept: $!";

my ($err, $hostname, $servicename) = getnameinfo($socket->peername);
die "Cannot getnameinfo - $err" if $err;

print "The peer is connected from $hostname\n";

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

use Socket qw(getnameinfo NIx_NOSERV);

my ($err, $hostname) = getnameinfo($socket->peername, 0, NIx_NOSERV);

Эта функция выполняет работу устаревших функций unpack_sockaddr_in(), inet_ntoa(), gethostbyaddr() и getservbyport().

На практике эту логику лучше реализовывать с помощью IO::Socket::IP.

Разрешение имён хостов в IP-адреса

Чтобы преобразовать имя хоста в удобочитаемый IP-адрес, используйте getaddrinfo() для преобразования имени хоста в список структур сокета, а затем getnameinfo() для каждого, чтобы снова сделать его удобочитаемым IP-адресом.

use Socket qw(:addrinfo SOCK_RAW);

my ($err, @res) = getaddrinfo($hostname, "", {socktype => SOCK_RAW});
die "Cannot getaddrinfo - $err" if $err;

while( my $ai = shift @res ) {
    my ($err, $ipaddr) = getnameinfo($ai->{addr}, NI_NUMERICHOST, NIx_NOSERV);
    die "Cannot getnameinfo - $err" if $err;

    print "$ipaddr\n";
}

socktype подсказка для getaddrinfo() фильтрует результаты, чтобы включить только один тип сокета и протокол. Без этого большинство ОС возвращают три комбинации, для SOCK_STREAM, SOCK_DGRAM и SOCK_RAW, что приводит к тройному выводу адресов. Флаг NI_NUMERICHOST для getnameinfo() заставляет его возвращать строковое представление простого IP-адреса, а не повторно разрешать его в имя хоста.

Эта комбинация выполняет работу устаревших функций gethostbyname() и inet_ntoa().

Доступ к параметрам сокета

Многие SO_* и другие константы предоставляют имена параметров сокета для getsockopt() и setsockopt().

use IO::Socket::INET;
use Socket qw(SOL_SOCKET SO_RCVBUF IPPROTO_IP IP_TTL);

my $socket = IO::Socket::INET->new(LocalPort => 0, Proto => 'udp')
    or die "Cannot create socket: $@";

$socket->setsockopt(SOL_SOCKET, SO_RCVBUF, 64*1024) or
    die "setsockopt: $!";

print "Receive buffer is ", $socket->getsockopt(SOL_SOCKET, SO_RCVBUF),
    " bytes\n";

print "IP TTL is ", $socket->getsockopt(IPPROTO_IP, IP_TTL), "\n";

Для удобства метод setsockopt() модуля IO::Socket преобразует число в упакованный байтовый буфер, а getsockopt() распакует байтовый буфер правильного размера обратно в число.

АВТОР

Этот модуль изначально поддерживался в ядре Perl разработчиками Perl 5.

Он был выделен в двойной жизни на CPAN на версии 1.95 Павлом Эвансом <leonerd@leonerd.org.uk>

© 1993–2020 Larry Wall and others
Licensed under the GNU General Public License version 1 or later, or the Artistic License.
The Perl logo is a trademark of the Perl Foundation.
https://perldoc.perl.org/5.28.3/Socket

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API