Wednesday, October 14, 2009

Sending to Multiple Hosts
























Network
Programming with Perl
By
Lincoln D. Stein
Slots : 1
Table
of Contents
Chapter 18.  The UDP
Protocol






    Content







Sending to Multiple Hosts


One of the nice features of UDP is that the
same socket can be used to send to and receive messages from
multiple hosts. To illustrate this, let's rewrite the daytime
client so that it can ask for the time from multiple
hosts.


The revised client reads a list of hostnames
from the command line and sends a daytime request to each one.
It then enters a loop in which it calls recv()
repeatedly to read any responses returned by the server. The
loop quits when the number of responses received matches the
number of requests sent, or until a preset timeout occurs. As
it receives each response, the client prints the name of the
remote host and the time it returned. Figure
18.3 lists the code for the revised daytime client, class=docEmphasis>udp_daytime_multi.pl.



Figure 18.3.
This time-of-day client contacts multiple hosts




Lines 1�7: Initialize script We
bring in the IO::Socket module and its constants. We again
declare the MAX_MSG_LEN constant and define a
timeout of 10 seconds for the receipt of all the responses.
As before, we set the input record separator to
CRLF.




Line 8: Set up a signal handler We
will use alarm() to set the timeout on received
responses, so we install an ALRM signal handler,
which simply dies with an appropriate message.




Line 9: Create socket We call
IO::Socket::INET->new() with a class=docEmphStrong>Proto argument of " udp
" to create a UDP socket. Because we will specify the
destination address within send() and don't want
IO::Socket to perform an automatic connect(), we do
not provide PeerPort or
PeerAddr arguments.




Line 10: Look up the daytime port We
look up the port number for the UDP version of the daytime
service using getservbyname().




Lines 11�20: Send request to all
hosts
We now send a request to each host that is given
on the command line. For each host we use
inet_aton() to translate its name into a packed IP
address, and sockaddr_in() to create a suitable
destination address.


We now send a request to the time-of-day
server running on the indicated host. As before, the exact
content of the request is irrelevant. If send()
reports that the message was successfully queued, we bump up
the $host_count counter. Otherwise, we warn about
the error.




Lines 21�32: Wait for responses We
are now going to wait for up to TIMEOUT seconds for
all the responses to come in. If we get all the responses we
are expecting, we leave the loop early. We call
alarm() to set the timeout and enter a loop that
decrements $host_count each time through. Within
the body of the loop, we call recv(). If
recv() returns false, then an error has occurred
and we print the contents of $! and go on to the
next iteration of the loop.


If recv() succeeds, it places the
received message into $daytime. We now attempt to
recover the hostname of the sender of the message we just
received. Recall that IO::Socket::INET conveniently
remembers the peer address from themost recent invocation of
recv(). We fetch this address by calling
peeraddr() and pass it to gethostbyaddr()
to translate it into a DNS name. If gethostbyaddr()
fails, we call the socket's peerhost() method to
translate the packed peer address into a dotted-quad IP
address string.


We remove the terminal CRLF from
$daytime and print the time and the name of the
host that reported it.




Line 33: Turn off the alarm On
principle, we deactivate the alarm after the loop is done.
This isn't strictly necessary because the program will exit
immediately anyway.



Here is what I saw when I ran the client
against several machines located in various parts of the
world. Notice that we got a delayed " Connection
refused
" message from one of the machines, but we can't
easily determine which one generated the error (except by a
process of elimination). Finally, notice that the responses
don't come back in the same order in which we submitted the
requests!

% udp_daytime_multi.pl sunsite.auc.dk rtfm.mit.edu wuarchive.wustl.edu
prep.ai.mit.edu

sent to sunsite.auc.dk...
sent to rtfm.mit.edu...
sent to wuarchive.wustl.edu...
sent to prep.ai.mit.edu...

Waiting for responses...
PENGUIN-LUST.MIT.EDU: Thu Aug 17 05:57:50 2000
wuarchive.wustl.edu: Thu Aug 17 04:57:52 2000
Connection refused
sunsite.auc.dk: Thu Aug 17 11:57:54 2000

Aside from the time-zone differences, the
three machines that responded reported the same time, plus or
minus a few seconds. It is likely that they are running XNTP
servers, a UDP-based protocol for synchronizing clocks with an
authoritative source.









       




    Top

    No comments:

    Post a Comment