Network Programming with Perl


 
Network Programming with Perl

By Lincoln  D.  Stein

Slots : 1

Table of Contents
Chapter  18.   The UDP Protocol

    Content

UDP Servers

UDP servers are generally much simpler in design than their TCP brethren. A typical UDP server is a simple loop that receives a message from an incoming client, processes it, and transmits a response. A server may handle requests from different clients with each iteration of the loop.

Because there's no long- term relationship between client and server, there's no need to manage connections, maintain concurrency, or retain state for an extended time. By the same token, a UDP server must be careful to process each transaction quickly or it may delay the response to waiting requests.

We will look at UDP servers in more detail in Chapter 19. In this chapter, we show a very simple example of a UDP client/server pair.

A UDP Reverse-Echo Server

For this example, we reimplement the reverse-echo server from Chapter 4 (Figure 4.2). As you recall, this server reads lines of input from the socket, reverses them, and echoes them back. Figure 18.4 lists the code.

Figure 18.4. A UDP reverse-echo server

Lines 1 “7: Initialize module We load the IO::Socket module and initialize our constants. The MY_ECHO_PORT constant should be set to an unused port on your system. We allow our port number to be changed at runtime using a command-line argument. If this argument is present, we recover it and store it in $port .

Line 8: Install INT handler We install an INT handler so that the server exits gracefully when the interrupt key is pressed. Microsoft Windows users will want to comment this out to avoid Dr. Watson errors.

Lines 9 “10: Create the socket We call IO:Socket::INET->new() to create a UDP socket bound to the port specified on the command line. The LocalPort argument is required to bind to the correct port, but as with TCP sockets there's no need to provide LocalAddr explicitly. IO::Socket::INET assumes INADDR_ANY , allowing the socket to receive messages on any of the host's network interfaces.

Lines 11 “21: Main loop We enter an infinite loop. Each time through the loop we call the socket's recv() method, copying the message into $msg_in . If for some reason we encounter an error, we just continue with the next iteration of the loop.

After accepting a message, we call the socket's peeraddr() method to recover the packed address of the sender, and attempt to translate it into a DNS hostname as before. If this fails, we retrieve the dotted -quad form of the peer's IP address. The call to peerport() returns the sender's port number. We print a status message to standard error and generate a response consisting of the client's message reversed end-to-end.

We now take advantage of another trick in the IO::Socket module. As mentioned earlier, if you call the send() method immediately after recv() , IO::Socket uses the stored peer address as its default destination. This means that we do not have to explicitly pass the destination address to send() . This reduces the idiom to a succinct:

$sock->send($msg_out) or die "send(): $!\n"; # (line 21)

Line 22: Close the socket Although this statement is never reached, we call the socket's close() method at the end of the script.

UDP Echo Client

We need a client to go along with this server. A suitable one is shown in Figure 18.5.

Figure 18.5. Echo client

Lines 1 “8: Initialization We load the IO::Socket module and initialize our constants and global variables . We use the standard " echo " service port as our default. This can be overridden on the command line, for instance to talk to the reverse-echo server discussed in the previous section.

Lines 9 “10: Create socket We create a new IO::Socket::INET object, requesting the UDP protocol and specifying a PeerAddr that combines the selected hostname and port number. Because we know in advance that the socket will be used to send messages to only one single host, we allow IO::Socket to call connect() .

Lines 11 “16: Main loop We read a line of input from standard input, then remove the terminal newline and send() it to the server. We don't need to specify a destination address, because the default destination has been set with connect() . We then call recv() to receive a response and print it to standard output.

Line 17: Close the socket The loop exits when standard input is closed. We close the socket by calling its close() method.

I launched the echo server from the previous section on the machine brie.cshl.org and ran the client on another machine, being careful to specify port 2007 rather than the default echo port. The transcript from the client session looked like this:

% udp_echo_cli1.pl brie.cshl.org 2007 hello there ereht olleh what's up? ?pu s'tahw goodbye eybdoog ^D

Meanwhile, on the server machine, these messages were printed.

% udp_echo_serv.pl servicing incoming requests.... Received 11 bytes from [brie.cshl.org,1048] Received 10 bytes from [brie.cshl.org,1048] Received 7 bytes from [brie.cshl.org,1048]

If other clients had sent requests during the same period of time, the server would have processed them as well and printed an appropriate status message.


   
Top

Категории