17.4. Setting Up a UDP ClientProblemYou want to exchange messages with another process using UDP (datagrams). SolutionTo set up a UDP socket handle, use either the low-level Socket module on your own filehandle: use Socket; socket(SOCKET, PF_INET, SOCK_DGRAM, getprotobyname("udp")) or die "socket: $!"; or else IO::Socket, which returns an anonymous one: use IO::Socket; $handle = IO::Socket::INET->new(Proto => 'udp') or die "socket: $@"; # yes, it uses $@ here
Then to send a message to a machine named $ipaddr = inet_aton($HOSTNAME); $portaddr = sockaddr_in($PORTNO, $ipaddr); send(SOCKET, $MSG, 0, $portaddr) == length($MSG) or die "cannot send to $HOSTNAME($PORTNO): $!";
To receive a message of length no greater than $ $portaddr = recv(SOCKET, $MSG, $MAXLEN, 0) or die "recv: $!"; ($portno, $ipaddr) = sockaddr_in($portaddr); $host = gethostbyaddr($ipaddr, AF_INET); print "$host($portno) said $MSG\n"; DiscussionDatagram sockets are unlike stream sockets. Streams provide sessions, giving the illusion of a stable connection. You might think of them as working like a telephone call - expensive to set up, but once established, reliable and easy to use. Datagrams, though, are more like the postal system - it's cheaper and easier to send a letter to your friend on the other side of the world than to call them on the phone. Datagrams are easier on the system than streams. You send a small amount of information one message at a time. But your messages' delivery isn't guaranteed, and they might arrive in the wrong order. Like a small post box, the receiver's queue might fill up and cause further messages to be dropped. Why then, if datagrams are unreliable, do we have them? Because some applications are most sensibly implemented in terms of datagrams. For instance, in streaming audio, it's more important that the stream as a whole be preserved than that every packet get through, especially if packets are being dropped because there's not enough bandwidth for them all. Another use for datagrams is broadcasting, which corresponds to mass mailing of advertisements in the postal model, and is equally popular in most circles. One use for broadcast packets is to send out a message to your local subnet saying "Hey, is there anybody around here who wants to be my server?"
Because datagrams don't provide the illusion of a lasting connection, you get a little more freedom in how you use them. You don't have to send(MYSOCKET, $msg_buffer, $flags, $remote_addr) or die "Can't send: $!\n"; The only flag argument used much is MSG_OOB, which lets you send and receive out-of-band data in advanced applications.
The remote address should be a port and internet address combination returned by the Socket module's
Example 17.1
is a small example of a UDP program. It contacts the UDP time port of the machine whose name is given on the command line, or of the local machine by default. This doesn't work on all machines, but those with a server will send you back a 4-byte integer packed in network byte order that represents the time that machine thinks it is. The time returned, however, is in the number of seconds since 1900. You have to subtract the number of seconds between 1900 and 1970 to feed that time to the Example 17.1: clockdrift#!/usr/bin/perl # clockdrift - compare another system's clock with this one use strict; use Socket; my ($host, $him, $src, $port, $ipaddr, $ptime, $delta); my $SECS_of_70_YEARS = 2_208_988_800; socket(MsgBox, PF_INET, SOCK_DGRAM, getprotobyname("udp")) or die "socket: $!"; $him = sockaddr_in(scalar(getservbyname("time", "udp")), inet_aton(shift || '127.1')); defined(send(MsgBox, 0, 0, $him)) or die "send: $!"; defined($src = recv(MsgBox, $ptime, 4, 0)) or die "recv: $!"; ($port, $ipaddr) = sockaddr_in($src); $host = gethostbyaddr($ipaddr, AF_INET); my $delta = (unpack("N", $ptime) - $SECS_of_70_YEARS) - time(); print "Clock on $host is $delta seconds ahead of this one.\n";
If the machine you're trying to contact isn't alive or if its response is lost, you'll only know because your program will get stuck in the See Also
The
Copyright © 2001 O'Reilly & Associates. All rights reserved. |
|