Perl 'Expert' Quiz-of-the-Week #3
Mark Jason Dominus <[email protected]> Wed, 30 Oct 2002 16:09:40 -0500
| Newsgroups | gmane.comp.lang.perl.qotw.quiz-of-the-week |
|---|---|
| Organization | Plover Systems |
| Message-ID | <[email protected]> |
IMPORTANT: Please do not post solutions, hints, or other spoilers
until at least 60 hours after the date of this message.
Thanks.
IMPORTANTE: Por favor, no enviéis soluciones, pistas, o cualquier otra
cosa que pueda echar a perder el concurso hasta que hayan
pasado por lo menos 60 horas desde la recepción de este
mensaje. Gracias.
IMPORTANT: S'il vous plaît, ne postez pas de solutions, indices ou
autre révélations jusqu'à au moins 60 heures après la date de
ce message. Merci
----------------------------------------------------------------
Perl provides a function, 'gethostbyname()', to translate host names
to their addresses. For example,
gethostbyname("perl.plover.com")
returns the string
\xd8\x9e\x34\x79
because that is the packed 4-byte IP address of perl.plover.com.
Unfortunately, gethostbyname() has a drawback. It typically consults
the DNS (domain name system) network service, and resolving a hostname
make require many network queries. Sending these queries and
receiving the answers or waiting for the timeouts can take a lot of
time, so a Perl program might hang for a long time whenever it does
'gethostbyname'.
You will write a replacement for gethostbyname() that does not suffer
from this drawback; it will be asynchronous. The replacement will
have two parts:
1. An asynchronous domain lookup server. This is a program that runs
continually in the background, waiting for requests from clients
to look up hostnames.
There must be some way for a client process to contact the server
and send it a hostname. The server must immediately return some
sort of token that identifies the query uniquely. The server then
performs the gethostbyname() call on behalf of the client.
There must be some way for the client to find out whether or not
the address has been obtained, and, if so, what the address is,
using the previously-returned token to specify which previous
query it is inquiring about. Finding out whether and answer is
ready must be instantaneous. If the answer is ready, finding out
the address must be instantaneous.
2. A Perl module that provides an interface to the asynchronous
lookup service. The interface will look like this:
use Gethostbyname::Asynchronous;
my $query = Gethostbyname::Asynchronous->query("perl.plover.com");
until ($query->is_ready) {
# ... do something else ...
}
# At this point, the service has located the address for us
my $address = $query->answer;
The ->answer method always returns the answer. If the answer
isn't ready at the time the call is made, then ->answer waits
until an answer is available and then returns it.
The module must allow multiple simultaneous queries:
for my $name (@names) {
$address{$name} = Gethostbyname::Asynchronous->query($name);
}
while (...) {
# ...do something else for a while...
for my $host (keys %address) {
if ($address{$host}->is_ready) {
print "$host: ", $address{$host}->answer, "\n";
delete $address{$host};
}
}
# More other stuff going on here...
}
If you're not familiar with OOP techniques in Perl, you may
implement a functional-style interface instead:
use Gethostbyname::Asynchronous::Functional;
my $qid = query("perl.plover.com");
until (is_ready($qid)) {
# ... do something else ...
}
# At this point, the service has located the address for us
my $address = answer($qid);