POE::C...solver(3pm)
π POE::Component::Resolver π
okay bestie, gather round, because we're talking about POE::Component::Resolver β that's the POE::Component::Resolver module from the User Contributed Perl Documentation, version 0.921, and it's literally the thing that saves your whole program from dying while DNS does its lil thing. no cap. π¦
β¨ NAME β¨
POE::Component::Resolver β a non-blocking getaddrinfo() resolver. it's giving "I do the waiting so you don't have to." π
πΈ VERSION πΈ
version 0.921 π
π SYNOPSIS π
okay so here's the whole vibe, verbatim, don't touch a single character:
#!/usr/bin/perl
use warnings;
use strict;
use POE;
use POE::Component::Resolver qw(AF_INET AF_INET6);
my $r = POE::Component::Resolver->new(
max_resolvers => 8,
idle_timeout => 5,
af_order => [ AF_INET6, AF_INET ],
# sidecar_program => $path_to_program,
);
my @hosts = qw( ipv6-test.com );
my $tcp = getprotobyname("tcp");
POE::Session->create(
inline_states => {
_start => sub {
foreach my $host (@hosts) {
$r->resolve(
host => $host,
service => "http",
event => "got_response",
hints => { protocol => $tcp },
) or die $!;
}
},
_stop => sub { print "client session stopped\n" },
got_response => sub {
my ($error, $addresses, $request) = @_[ARG0..ARG2];
use YAML; print YAML::Dump(
{
error => $error,
addr => $addresses,
req => $request,
}
);
},
}
);
POE::Kernel->run();
like. look at it. it's beautiful. π
π DESCRIPTION π
POE::Component::Resolver runs Socket::getaddrinfo() calls in subprocesses, where they're allowed to block for as long as they need to. that's the whole trick bestie β the blocking goes in the baby process, not your main character event loop. π§
by default it runs eight subprocesses and prefers address families in whatever order getaddrinfo() hands them back. you can override both of those defaults with constructor parameters. and fyi, getaddrinfo() delegates to your operating system's resolver, which may itself be reconfigured according to the usual conventions. iykyk. π
π PUBLIC METHODS π
π new
makes you a brand new resolver. returns an object that you must hold onto and use to make requests. check the synopsis above for the whole picture. β¨
it accepts up to four optional named parameters.
af_orderβ may contain an arrayref of the address families to permit, in the order they're preferred. withoutaf_order, the component will prefer IPv4 addresses over IPv6 for legacy compatibility. this may change in the future as IPv6 gains more widespread acceptance. and psst β check"ENVIRONMENT VARIABLES"for a way to override the default without hacking modules. π
# Prefer IPv6 addresses, but also return IPv4 ones.
my $r1 = POE::Component::Resolver->new(
af_order => [ AF_INET6, AF_INET ]
);
# Only return IPv6 addresses,
# or nothing in cases where only IPv4 addresses exist.
my $r2 = POE::Component::Resolver->new(
af_order => [ AF_INET6 ]
);
idle_timeoutβ decides how long to keep idle resolver subprocesses around before cleaning them up, in seconds. defaults to15.0seconds. β³max_resolversβ controls the component's parallelism by defining the max number of sidecar processes to manage. defaults to8, but you can go fewer or more depending on the resources you have and how much parallelism you actually need. β¨
# One at a time, but without the pesky blocking.
my $r3 = POE::Component::Resolver->new( max_resolvers => 1 );
sidecar_programβ the disk location of a program that will perform blocking lookups on standard input and print the results on standard output. the sidecar program is only needed in special environments where bundling and executing extra utilities is tricky. PAR is one such environment.
the sidecar program needs to contain at least two statements:
use POE::Component::Resolver::Sidecar;
POE::Component::Resover::Sidecar->main();
bestie i am COPYING that verbatim, typos and all, because the rule is the rule. π
π¦ resolve
resolve() kicks off a new request to resolve a domain. the request gets enqueued in the component until a sidecar process is free to service it. resolve() returns a request ID that you can use to cancel() a request before it's done β or undef if the request couldn't even begin (like during shutdown, oop π). resolve requires two parameters and accepts some extra optional ones.
hostandserviceβ required. contain the host (name or Internet address) and service (name or numeric port) that get passed verbatim togetaddrinfo(). see Socket for details.eventβ optional. contains the name of the event that will carry the resolver response. if you omit it, it defaults toresolver_response; you may wanna specify a shorter event name tbh.hintsβ optional. if you specify it, it must contain a hashref of hints exactly asgetaddrinfo()expects them. see Socket for details.miscβ optional continuation data that gets passed back in the response. it can contain literally any type of data your application needs. π
π cancel
cancel a request, given the request's ID.
my $request_id = $resolver->resolve("poe.dyndns.org", "http");
$resolver->cancel($request_id);
πΈ shutdown
shut down the resolver. POE::Component::Resolver retains resources β including child processes β for up to idle_timeout seconds. this may keep programs running up to idle_timeout seconds longer than they should. π
POE::Component::Resolver will release its resources (including child processes) when its shutdown() method is called. periodt.
β unpack_addr
in scalar context, unpack_addr($response_addr_hashref) returns the addr element of $response_addr_hashref in a numeric form appropriate for the address family of the address.
sub handle_resolver_response {
my ($error, $addresses, $request) = @_[ARG0..ARG2];
foreach my $a (@$addresses) {
my $numeric_addr = $resolver->unpack_addr($a);
print "$request->{host} = $numeric_addr\n";
}
}
in list context, it returns the numeric port and address.
sub handle_resolver_response {
my ($error, $addresses, $request) = @_[ARG0..ARG2];
foreach my $a (@$addresses) {
my ($$numeric_addr, $port) = $resolver->unpack_addr($a);
print "$request->{host} = $numeric_addr\n";
}
}
unpack_addr() is a convenience wrapper around getnameinfo() from Socket. you're certainly welcome to use the discrete function instead, no pressure bestie. π«Ά
unpack_addr() returns bleak emptiness on failure, regardless of context. you can check for an undef return.
π PUBLIC EVENTS π
π resolver_response
the resolver response event includes three parameters.
$_[ARG0] and $_[ARG1] contain the retrn values from Socket's getaddrinfo() call. these are an error message (if the call failed), and an arrayref of address structures if the call succeeded. π₯
the component provides its own error message, 'component shut down'. this response is given for every pending request at the time the user shuts down the component.
$_[ARG2] contains a hashref of information provided to the resolve() method. specifically, the values of resolve()'s host, service and misc parameters. π
π ENVIRONMENT VARIABLES π
π§ POCO_RESOLVER_IPV
the POCO_RESOLVER_IPV environment variable sets this component's default Internet Protocol Version search order. if the variable exists, it should contain a string with the numbers 4 and/or 6. POE::Component::Resolver will treate these as Internet Protocol versions to consider, in the order they are preferred. π
POE::Component::Resolver's new() method accepts an af_order parameter that overrides this environment variable.
default to IPv4 addresses only:
export POCO_RESOLVER_IPV=4
default to IPv6 addresses only:
export POCO_RESOLVER_IPV=6
prefer IPv6, but accept IPv4 if needed:
export POCO_RESOLVER_IPV=64
prefer IPv4, but accept IPv6 if needed:
export POCO_RESOLVER_IPV=46
π COMPATIBILITY ISSUES π
π Microsoft Windows
this module requires "Microsoft TCP/IP version 6" to be installed. steps for Windows XP Pro (the steps for your particular version of Windows may be subtly or drastically different):
- open your Control Panel
- open your Network Connections
- select your network connection from the available one(s)
- in the Local Area Connection Status dialog, click the Properties button
- if
"Microsoft TCP/IP version 6"is listed as an item being used, you are done. β - otherwise click Install...
- choose to add a Protocol
- and install
"Microsoft TCP/IP version 6"from the list of network protocols.
π BUGS π
- there is no timeout on requests. (yes really. i know. screaming.)
- there is no way to cancel a pending request.
not me pointing out the cancel method exists and then the bugs section saying there's no way to cancel a pending request. bestie, i don't make the rules, i just report them faithfully. π
π TROUBLESHOOTING π
πΈ programs linger for several seconds before exiting
programs should shutdown() their POE::Component::Resolver objects when they're through needing asynchronous DNS resolution. programs should additionally destroy their resolvers if they intend to run awhile and want to reuse the memory they consume. π«Ά
in some cases, it may be necessary to shutdown components that perform asynchronous DNS using POE::Component::Resolver... such as POE::Component::IRC, POE::Component::Client::Keepalive and POE::Component::Client::HTTP.
by default, the resolver subprocesses hang around for idle_timeout, which defaults to 15.0 seconds. destroying the Resolver object will clean up the process pool. assuming only that is keeping the event loop active, the program will then exit cleanly. β¨
alternatively, reduce idle_timeout to a more manageable number, such as 5.0 seconds.
otherwise something else may also be keeping the event loop active. π
π LICENSE π
except where otherwise noted, this distribution is Copyright 2011 by Rocco Caputo. all rights reserved. this distribution is free software; you may redistribute it and/or modify it under the same terms as Perl itself.
and that's the whole thing bestie!! πβ¨π this was documented in perl v5.26.1, dated 2018-04-08, and it's POE::C...solver(3pm) in the manual β like, the header said so and everything. slay, go resolve some hostnames non-blockingly, you absolute icon. ππ¦π
π¦ where this page comes from
- debian bookworm: libpoe-component-resolver-perl 0.921-1 Β· Artistic-1.0-Perl OR GPL-1.0-or-later
- ubuntu jammy: libpoe-component-resolver-perl 0.921-1 Β· Artistic-1.0-Perl OR GPL-1.0-or-later
- ubuntu noble: libpoe-component-resolver-perl 0.921-1 Β· Artistic-1.0-Perl OR 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