Network Programming with Perl


 
Network Programming with Perl

By Lincoln  D.  Stein

Slots : 1

Table of Contents
Chapter  20.   Broadcasting

    Content

Enhancing the Chat Client to Support Resource Discovery

We now have all the ingredients on hand to add a useful feature to the UDP chat client developed in Chapter 19. If the client is launched without specifying a target server, it broadcasts requests to the chat port on whatever networks it finds itself attached to. It waits for responses from any chat servers that might be listening, and if a response is forthcoming from a host within a set time, the client connects to it and proceeds as before. In the case of multiple responses, the client binds to whichever server answers first. This is a simple form of resource discovery.

You'll find the code listing for the revised chat client in Figure 20.4. It is derived from the timed chat client of Chapter 19 (Figures 19.8, 19.9, and 19.10). Parts of the code that haven't changed are omitted from the listing.

Figure 20.4. Chat client with broadcasts

Line 8: Load the IO::Interface module We will use IO::Interface to derive the client's subnet-directed broadcast address(es), so we load the module, importing the interface flag constants at the same time.

Line 37: No default server address In previous incarnations of this client, we defaulted to localhost if the chat host was not specified on the command line. In this version, we assume no default, using an empty string for the server name if none was specified on the command line.

Lines 40 “41: Call find_server() to search for a server If no server address was specified on the command line, we call a new internal subroutine find_server() to locate one. If find_server() returns undef , we die.

Lines 64 “85: Find a server via broadcasts All the interesting work is in the find_server() subroutine. It begins by creating a new UDP socket. This socket happens to be distinct from the one that will ultimately be used to communicate with the server, but there's no reason they can't be the same. After creating the socket, we set its SO_BROADCAST option to a true value so that we can broadcast over it.

We now look for network interfaces to broadcast on. We get the list of interfaces by calling the socket's if_list() method and loop over them, looking for those that have the IFF_BROADCAST option set in their interface flags. For each broadcast-capable interface, we fetch its broadcast IP address, create a packed target address using the specified chat server port number, and send a message to it.

It doesn't matter what message we send to the server, because we care only whether a server responds at all. In this case, we send a message containing binary 0 in network order. Since this corresponds to none of the chat messages defined in the ChatCodes package, we expect the server to respond with a message code of ERROR . A more formal way to do this would be to define explicit messages that client and server could exchange for this purpose, but that would have required changes at the server end as well.

The client has broadcast the request to all its attached broadcast-capable interfaces, and now it must wait for responses. We use IO::Select to wait for up to 3 seconds for incoming messages. If no response is received before the timeout, we return undef . Otherwise, we read the first message, unpack it, and see if it contains the expected ERROR code from the chat server (if not, it may indicate that some other type of server is listening on the port). We now return the address of the sender by calling sockaddr_in() to unpack the peer name returned from recv() , and inet_ntoa() to turn the address into human-readable dotted -quad form.

If two or more chat servers received the broadcast, the client binds to the first one. The responses sent by other servers are discarded along with the socket when the subroutine goes out of scope.

When we run the modified chat client on a host that is attached to two networks, we see the client send broadcast packets to both networks. After a short interval, the client receives a response from a server on one of the networks and selects it. The remainder of the chat session proceeds as usual.

% broadcast_chat_client.pl Broadcasting for a server on 192.168.3.255 Broadcasting for a server on 192.168.8.255 Found a server at 192.168.3.2 Your nickname: lincoln trying to log in (1)... Log in successful. Welcome lincoln.


   
Top

Категории