IO::Socket::IP(3perl)
π NAME π
IO::Socket::IP β bestie, this is the family-neutral IP socket that supports both IPv4 and IPv6, and honestly? It's giving main character energy. β¨
π SYNOPSIS π
okay so here's the vibe, no cap:
use IO::Socket::IP;
my $sock = IO::Socket::IP->new(
PeerHost => "www.google.com",
PeerPort => "http",
Type => SOCK_STREAM,
) or die "Cannot construct socket - $IO::Socket::errstr";
my $familyname = ( $sock->sockdomain == PF_INET6 ) ? "IPv6" :
( $sock->sockdomain == PF_INET ) ? "IPv4" :
"unknown";
printf "Connected to google via %s\n", $familyname;
like yes, we're connecting to google and then figuring out whether it was over IPv6 or IPv4. iconic behaviour fr fr π¦
πΈ DESCRIPTION πΈ
This module gives you a protocol-independent way to use IPv4 and IPv6 sockets. It's literally designed to be the replacement for IO::Socket::INET, and most of the constructor arguments and methods are provided in a backward-compatible way β so you can mostly just swap it in and vibe. π
For the list of known differences, go peek at the "IO::Socket::INET" INCOMPATIBILITIES section below.
The way it works: it uses getaddrinfo(3) to turn hostnames and service names or port numbers into whole sets of possible addresses to connect to or listen on. So it happily does IPv6 where the system supports it, and still falls back to IPv4-only on systems that don't. adaptive queen. π
π REPLACING "IO::Socket" DEFAULT BEHAVIOUR π
If you drop -register into the import list for IO::Socket::IP, it'll register itself with IO::Socket as the class that handles PF_INET. It will also ask to handle PF_INET6 too, provided that constant is actually available. β¨
So like, changing "IO::Socket"'s default behaviour means that calling the "IO::Socket" constructor with either PF_INET or PF_INET6 as the Domain parameter will hand you back an "IO::Socket::IP" object. surprise! it's us. π«Ά
use IO::Socket::IP -register;
my $sock = IO::Socket->new(
Domain => PF_INET6,
LocalHost => "::1",
Listen => 1,
) or die "Cannot create socket - $IO::Socket::errstr\n";
print "Created a socket of type " . ref($sock) . "\n";
β οΈ heads up bestie: -register is a global setting that applies to the entire program. You can't apply it only for certain callers, you can't remove it, and you can't limit it by lexical scope. it's all-or-nothing, periodt.
π CONSTRUCTORS π
π§ new π§
$sock = IO::Socket::IP->new( %args )
Creates a shiny new "IO::Socket::IP" object, containing a newly created socket handle according to the named arguments you passed in. The recognised arguments are, and listen, there's a lot of them: β¬οΈ
PeerHost=> STRINGPeerService=> STRING β Hostname and service name for the peer toconnect()to. The service name may be given as a port number, as a decimal string. (yes, decimal string, don't come at me with hex.)PeerAddr=> STRINGPeerPort=> STRING β For symmetry with the accessor methods and compatibility with"IO::Socket::INET", these are accepted as synonyms for"PeerHost"and"PeerService"respectively. same thing, different name, cute.PeerAddrInfo=> ARRAY β Alternate form of specifying the peer toconnect()to. This should be an array of the form returned by"Socket::getaddrinfo". β β‘ This parameter takes precedence over the"Peer*","Family","Type"and"Proto"arguments. so if you set both, this one wins, no debate.LocalHost=> STRINGLocalService=> STRING β Hostname and service name for the local address tobind()to.LocalAddr=> STRINGLocalPort=> STRING β For symmetry with the accessor methods and compatibility with"IO::Socket::INET", these are accepted as synonyms for"LocalHost"and"LocalService"respectively. again: same energy, different name.LocalAddrInfo=> ARRAY β Alternate form of specifying the local address tobind()to. This should be an array of the form returned by"Socket::getaddrinfo". β β‘ This parameter takes precedence over the"Local*","Family","Type"and"Proto"arguments. same rule as before, it ate and left no crumbs.Family=> INT β The address family to pass to"getaddrinfo"(e.g."AF_INET","AF_INET6"). Normally this will be left undefined, and"getaddrinfo"will search using any address family supported by the system. let the system choose, she knows what she's doing. πType=> INT β The socket type to pass to"getaddrinfo"(e.g."SOCK_STREAM","SOCK_DGRAM"). Normally defined by the caller; if left undefined"getaddrinfo"may attempt to infer the type from the service name. detective work. πProto=> STRING or INT β The IP protocol to use for the socket (e.g.'tcp',"IPPROTO_TCP",'udp',"IPPROTO_UDP"). Normally this will be left undefined, and either"getaddrinfo"or the kernel will choose an appropriate value. May be given either in string name or numeric form.GetAddrInfoFlags=> INT β More flags to pass to thegetaddrinfo()function. If not supplied, a default of"AI_ADDRCONFIG"will be used. β These flags will be combined with"AI_PASSIVE"if the"Listen"argument is given. For more information see the documentation aboutgetaddrinfo()in the Socket module.Listen=> INT β If defined, puts the socket into listening mode where new connections can be accepted using the"accept"method. The value given is used as thelisten(2)queue size.ReuseAddr=> BOOL β If true, set the"SO_REUSEADDR"sockopt. slay.ReusePort=> BOOL β If true, set the"SO_REUSEPORT"sockopt (not all OSes implement this sockopt, so like, don't be shocked if it's not there π).Broadcast=> BOOL β If true, set the"SO_BROADCAST"sockopt.Sockopts=> ARRAY β An optional array of other socket options to apply after the three listed above. The value is an ARRAY containing 2- or 3-element ARRAYrefs. Each inner array relates to a single option, giving the level and option name, and an optional value. If the value element is missing, it will be given the value of a platform-sized integer1constant (i.e. suitable to enable most of the common boolean options). β For example, both options given below are equivalent to setting"ReuseAddr":
Sockopts => [
[ SOL_SOCKET, SO_REUSEADDR ],
[ SOL_SOCKET, SO_REUSEADDR, pack( "i", 1 ) ],
]
V6Only=> BOOL β If defined, set the"IPV6_V6ONLY"sockopt when creating"PF_INET6"sockets to the given value. If true, a listening-mode socket will only listen on the"AF_INET6"addresses; if false it will also accept connections from"AF_INET"addresses. β If not defined, the socket option will not be changed, and the default value set by the operating system will apply. β οΈ For repeatable behaviour across platforms it is recommended this value always be defined for listening-mode sockets. like, always. please. β Note that not all platforms support disabling this option. Some, at least OpenBSD and MirBSD, will fail with"EINVAL"if you attempt to disable it. To determine whether it is possible to disable, you may use the class method:
if( IO::Socket::IP->CAN_DISABLE_V6ONLY ) {
...
}
else {
...
}
β If your platform does not support disabling this option but you still want to listen for both "AF_INET" and "AF_INET6" connections, you will have to create two listening sockets, one bound to each protocol. sis had to split herself in two, we don't make the rules. π
MultiHomedβ This"IO::Socket::INET"-style argument is ignored, except if it is defined but false. See the"IO::Socket::INET"INCOMPATIBILITIES section below. β However, the behaviour it enables is always performed by"IO::Socket::IP". so like, it's doing it anyway, you don't need to ask.Blocking=> BOOL β If defined but false, the socket will be set to non-blocking mode. Otherwise it will default to blocking mode. See the NON-BLOCKING section below for more detail.Timeout=> NUM β If defined, gives a maximum time in seconds to block perconnect()call when in blocking mode. If missing, no timeout is applied other than that provided by the underlying operating system. When in non-blocking mode this parameter is ignored. β Note that if the hostname resolves to multiple address candidates, the same timeout will apply to each connection attempt individually, rather than to the operation as a whole. Further note that the timeout does not apply to the initial hostname resolve operation, if connecting by hostname. β This behaviour is copied inspired by"IO::Socket::INET"; for more fine grained control over connection timeouts, consider performing a nonblocking connect directly.
okay so if neither "Type" nor "Proto" hints are provided, a default of "SOCK_STREAM" and "IPPROTO_TCP" respectively will be set, to maintain compatibility with "IO::Socket::INET". And other named arguments that are not recognised? just ignored. we don't see them. π
If neither "Family" nor any hosts or addresses are passed, nor any *AddrInfo, then the constructor has literally no information on which to decide a socket family to create. In this case, it performs a "getaddrinfo" call with the "AI_ADDRCONFIG" flag, no host name, and a service name of "0", and uses the family of the first returned result. improvising! and it works! π
If the constructor fails, it will set $IO::Socket::errstr and $@ to an appropriate error message; this may be from $! or it may be some other string β not every failure necessarily has an associated "errno" value. so don't come crying to errno, she might not know anything. π
π new (one arg) π
$sock = IO::Socket::IP->new( $peeraddr )
As a special case, if the constructor is passed a single argument (as opposed to an even-sized list of key/value pairs), it is taken to be the value of the "PeerAddr" parameter. This is parsed in the same way, according to the behaviour given in the "PeerHost" AND "LocalHost" PARSING section below. cute little shortcut, iykyk. π
β¨ METHODS β¨
bestie. okay so beyond everything below, this class also inherits every single method from IO::Socket and IO::Handle. so like, the whole family tree, you get all of it. π
π« sockhost_service
( $host, $service ) = $sock->sockhost_service( $numeric );
gives you back the hostname AND the service name of the local address β i.e. the socket address that the sockname method hands you. two for one, iconic behavior honestly. β¨
if $numeric is true, they come back in numeric form instead of getting resolved into pretty names. no DNS drama, just numbers.
now, there are four convenience wrappers below that can grab one of these two values for you, but ngl β if you want both host and service name, call this method instead of the wrappers, because this one only hits getnameinfo(3) once. one call, two values. efficient queen. π
π« sockhost
$addr = $sock->sockhost;
returns the numeric form of the local address, as a textual representation. that's it, that's the whole method. π
π« sockport
$port = $sock->sockport;
returns the numeric form of the local port number.
π« sockhostname
$host = $sock->sockhostname;
returns the resolved name of the local address. (yes, the one with actual letters in it π)
π« sockservice
$service = $sock->sockservice;
returns the resolved name of the local port number.
π« sockaddr
$addr = $sock->sockaddr;
returns the local address as a binary octet string. raw bytes, no notes. π«Ά
π« peerhost_service
( $host, $service ) = $sock->peerhost_service( $numeric );
the exact same situation as sockhost_service up there, except it's the peer address β the one peername gives you. π
and same as before: if $numeric is true, you get numeric forms instead of resolved names.
the same four convenience wrappers apply here too, and again β if you need both host and service name, use this method, not the wrappers, because it calls getnameinfo(3) only once. save those syscalls, bestie. πΈ
π« peerhost
$addr = $sock->peerhost;
returns the numeric form of the peer address as a textual representation.
π« peerport
$port = $sock->peerport;
returns the numeric form of the peer port number.
π« peerhostname
$host = $sock->peerhostname;
returns the resolved name of the peer address.
π« peerservice
$service = $sock->peerservice;
returns the resolved name of the peer port number.
π« peeraddr
$addr = $peer->peeraddr;
returns the peer address as a binary octet string.
π« as_inet
$inet = $sock->as_inet;
returns a new IO::Socket::INET instance that wraps the same filehandle. super useful when something, for backward-compatibility reasons, demands a real actual object of IO::Socket::INET type and refuses to accept IO::Socket::IP. we've all been there. π
β οΈ WARNING β οΈ the new object wraps the same underlying socket filehandle as the original. so please, please, do not keep using both objects at the same time. care should be taken here. ideally you discard the original $sock right after you call this method. one socket, one owner. π
this method checks that the socket domain is PF_INET, and it will throw an exception if it isn't. no exceptions literally except, well, the exception. π
π NON-BLOCKING π
okay this is where it gets spicy. π₯
if the constructor gets a defined but false value for the Blocking argument, then the socket goes into non-blocking mode. and when you're in non-blocking mode, the socket will not be set up by the time the constructor returns β because otherwise the underlying connect(2) syscall would have to block, and we simply do not do that here. not today. π
this non-blocking behaviour is an extension of the IO::Socket::INET API, and it's unique to IO::Socket::IP, because the former doesn't support multi-homed non-blocking connect. so like, we're the upgrade. π¦
when you're using non-blocking mode, the caller has to repeatedly check for writeability on the filehandle β for instance using select or IO::Poll. each time the filehandle is ready to write, you must call the connect method with no arguments. and heads up: some operating systems, most notably MSWin32, do not report a connect() failure using write-ready β so you also have to select() for exceptional status. do not skip that part fr fr. π
while connect returns false, the value of $! tells you whether you should try again (by being set to EINPROGRESS, or EWOULDBLOCK on MSWin32), or whether a permanent error has happened (e.g. ECONNREFUSED). read your $!, bestie, it's literally telling you what to do. π
once the socket has connected to the peer, connect returns true and the socket is ready to use. slay. β¨
β οΈ NOTE calls to the platform's underlyinggetaddrinfo(3)function may block. ifIO::Socket::IPhas to do this lookup, the constructor will block even when in non-blocking mode. the vibe check fails. π
to dodge that blocking behaviour, the caller should pass in the result of such a lookup using the PeerAddrInfo or LocalAddrInfo arguments. you can get that by using Net::LibAsyncNS, or you can just call the getaddrinfo(3) function in a child process. your call. π
use IO::Socket::IP;
use Errno qw( EINPROGRESS EWOULDBLOCK );
my @peeraddrinfo = ... # Caller must obtain the getaddrinfo result here
my $socket = IO::Socket::IP->new(
PeerAddrInfo => \@peeraddrinfo,
Blocking => 0,
) or die "Cannot construct socket - $@";
while( !$socket->connect and ( $! == EINPROGRESS || $! == EWOULDBLOCK ) ) {
my $wvec = '';
vec( $wvec, fileno $socket, 1 ) = 1;
my $evec = '';
vec( $evec, fileno $socket, 1 ) = 1;
select( undef, $wvec, $evec, undef ) or die "Cannot select - $!";
}
die "Cannot connect - $!" if $!;
...
the example above uses select(), but literally any similar mechanism should work analogously. π«Ά
and here's the cute part: IO::Socket::IP takes care, when creating new socket filehandles, to preserve the actual file descriptor number β so techniques like poll or epoll should be totally transparent to its reallocation of a different socket underneath, maybe even in order to switch protocol family between PF_INET and PF_INET6. main character energy, honestly. π
for another example using IO::Poll and Net::LibAsyncNS, go look at the examples/nonblocking_libasyncns.pl file in the module distribution. π¦
πΈ PeerHost AND LocalHost PARSING πΈ
so, to support the IO::Socket::INET API, the host and port info can be passed in a single string instead of as two separate arguments. one string, two facts. efficient. π
if either LocalHost or PeerHost (or their ...Addr synonyms) has any of these special forms, then special parsing kicks in:
the value of the ...Host argument gets split to give you both the hostname and the port (or service name):
hostname.example.org:http # Host name
192.0.2.1:80 # IPv4 address
[2001:db8::1]:80 # IPv6 address
in each case, the port or service name (e.g. 80) is passed as the LocalService or PeerService argument. π
either LocalService or PeerService (or their ...Port synonyms) can be a service name, a decimal number, or a string containing both a service name and a number, in a form like:
http(80)
in that case, the name (http) gets tried first, but if the resolver doesn't understand it, then the port number (80) will be used instead. best of both, backup plan included. π«Ά
and if the ...Host argument is in this special form and the corresponding ...Service or ...Port argument is also defined β the one parsed from the ...Host argument wins, and the other one is ignored. it takes precedence, periodt. π
π« split_addr
( $host, $port ) = IO::Socket::IP->split_addr( $addr )
utility method that does exactly the parsing described above. returns a 2-element list containing either the split hostname and port description if it could be parsed, or the given address and undef if it wasn't recognized. one or the other, no in-between. π
IO::Socket::IP->split_addr( "hostname:http" );
# ( "hostname", "http" )
IO::Socket::IP->split_addr( "192.0.2.1:80" );
# ( "192.0.2.1", "80" )
IO::Socket::IP->split_addr( "[2001:db8::1]:80" );
# ( "2001:db8::1", "80" )
IO::Socket::IP->split_addr( "something.else" );
# ( "something.else", undef )
π« join_addr
$addr = IO::Socket::IP->join_addr( $host, $port )
the reverse of split_addr β it returns a string formed by joining the given host address and port number together. and if the host address needs it, it gets wrapped in [] brackets (because it's a raw IPv6 numeric address). cute little brackets. π
this is especially useful when combined with the sockhost_service or peerhost_service methods. like:
say "Connected to ", IO::Socket::IP->join_addr( $sock->peerhost_service );
look at that. one line. flawless. π
π IO::Socket::INET INCOMPATIBILITIES π
okay so there are a couple things where we simply do not match ::INET, and here's why:
- the behaviour enabled by
MultiHomedis in fact implemented byIO::Socket::IP, because it's required to correctly support searching for a useable address from the results of thegetaddrinfo(3)call. the constructor will ignore the value of this argument β except if it's defined but false. in that case an exception is thrown, because that would be requesting to disable thegetaddrinfo(3)search behaviour in the first place. so don't. π IO::Socket::IPimplements both theBlockingandTimeoutparameters, but it implements the interaction of both in a different way. let me explain:
in ::INET, supplying a timeout overrides the non-blocking behaviour, meaning the connect() operation will still block even though the caller literally asked for a non-blocking socket. this is not explicitly specified in its documentation, and this author doesn't believe it's a useful behaviour β it appears to come from a quirk of implementation. a little oopsie, if you will. π
in ::IP therefore, the Blocking parameter takes precedence β if a non-blocking socket is requested, no operation will block. periodt. the Timeout parameter here simply defines the maximum time that a blocking connect() call will wait, if it blocks at all.
so if you specifically want that "blocking connect then non-blocking send and receive" behaviour that you get by specifying this combination of options to ::INET while using ::IP, you do it in two steps: first a blocking connect, then afterwards turn the socket into nonblocking mode. like this:
my $sock = IO::Socket::IP->new(
PeerHost => $peer,
Timeout => 20,
) or die "Cannot connect - $@";
$sock->blocking( 0 );
this code will behave identically under both IO::Socket::INET and IO::Socket::IP. π slay.
π TODO π
- Investigate whether
POSIX::dup2upsets BSD'skqueuewatchers, and if so, consider what possible workarounds might be applied. the mystery continues... π΅οΈββοΈ
π AUTHOR π
Paul Evans <leonerd@leonerd.org.uk>
and that's the whole page, bestie!! π«Άβ¨ you made it. this was IO::Socket::IP(3perl), from perl v5.44.0, dated 2026-10-17. go forth and connect responsibly. bye queen π
π
π¦ where this page comes from
- arch rolling: perl 5.44.0-1 Β· Artistic-1.0-Perl AND GPL-1.0-or-later
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms