-->

Previous | Table of Contents | Next

Page 590

UDP, like SOCK_DGRAM, is connectionless and unreliable. Applications have to provide whatever reliability mechanisms are necessary for the job that they are performing. For some applications, that is an advantage because all the mechanisms provided by TCP aren't always needed. For example, DNS, which uses UDP, simply sends a message and waits for a response for a predetermined interval; because DNS is a one-to-one message-to-response protocol, sequencing between client and server is not necessary. UDP is connectionless, so a server can use one socket to communicate with many clients. All clients write to the same address for the server, and the server responds individually by writing to specific client addresses.

UDP messages can also be broadcast to entire networks, which is a blessing to the application that needs to communicate one message to many users, but a curse for the workstations that don't need the message but have to read it in order to figure out that it isn't for them. The ability to broadcast messages over UDP and the fact that the connectionless aspect of UDP makes it difficult to verify the source of messages are two of the reasons why many networking people consider the protocol to be a security risk and dislike even enabling it within their organizations.

Making a Connection

Logically, if you are creating a connection like that of the makeconn() function in Listing 28.1, you need to create a SOCK_STREAM socket with the TCP protocol information retrieved with getprotobyname() in line 15. Take a look at lines 27 and 28 from Listing 28.1, repeated here:

27:  socket(CONNFD, PF_INET, SOCK_STREAM, $proto);

28:  connect(CONNFD, $servaddr) or die "connect : $!";

After creating the socket in line 27, you then pass it to connect() with the address structure created by sockaddr_in(). The connect() function actually contacts the address specified in the structure and establishes the virtual circuit supported by TCP.

A TCP Client Example

Listing 28.3 puts makeconn() to work in a sample program. client1 can be found on the book's CD-ROM.

Listing 28.3. client1.

#!/usr/bin/perl

use Socket;

require "./network.pl";



$NETFD = makeconn($ARGV[0], $ARGV[1]);



#

# Get the message

#

sysread $NETFD, $message, 32768 or die "error getting message : $!";

print "$message \n";

close $NETFD;

Page 591

Run this program with two command-line arguments, the name of a Linux host that is running sendmail and the mail port name, smtp:

$ ./client1 iest smtp

220 iest.home.mxn.com ESMTP Sendmail 8.8.5/8.8.5; Sat, 4 Oct 1997 18:25:08 -0400

This program uses makeconn() to connect to the sendmail program running on the named host and reads the greeting that it sends to a new client when it first connects, using the sysread() function.

sysread() is one of the functions used for extracting network messages from sockets. It is a wrapper for the UNIX read() system call. You cannot use the Perl read() function because it is designed for standard I/O, which uses buffering and other high-level features that interfere with network communications. In a real-world application, you would probably read messages with sysread() in and out of a buffer of your own and keep careful track of what you had just read because it is possible to be interrupted in a read call by a signal. (You would also install signal handlers.) As this example demonstrates, establishing a client connection and retrieving some data is pretty simple.

TIP
One of the benefits of using Perl for network programming is that it hides the issue of byte ordering between different architectures. Intel x86 chips and Sun SPARC chips, for example, represent values differently. The creators of the Internet introduced a concept of network byte order, which programs are supposed to place values in prior to transmission and have to translate back to their network format when they read in messages. Perl does this for us.

A TCP Server Example

Now you'll write your own server for client1 to connect to. First, you have to place a socket in the listen state. You'll use another function that is defined in network.pl, makelisten(), which is shown in Listing 28.4.

Listing 28.4. makelisten().

 1: sub makelisten {

 2:

 3:     my ($portname, $port, $proto, $servaddr);

 4:     $portname = $_[0];

 5:

 6:     #

 7:     #  port and protocol

 8:     #

 9:     $port = getservbyname($portname, `tcp') or


                                        continues

Page 592

Listing 28.4. continued

10:     die "getservbyname: cannot get port : $!";

11:     $proto = getprotobyname(`tcp') or

12:     die "getprotobyname: cannot get proto : $!";

13:

14:     #

15:     # Bind an inet address

16:     #

17:     socket(LISTFD, PF_INET, SOCK_STREAM, $proto);

18:     bind (LISTFD, sockaddr_in($port, INADDR_ANY)) or die "bind: $!";

19:     listen (LISTFD, SOMAXCONN) or die "listen: $!";

20:     return LISTFD;

21: }

The makelisten() function creates a TCP socket, binds it to a local address, and then places it in the listen state.

Lines 9 and 11 retrieve the same information that makeconn() retrieves in order to create a connection, with the exception of an internet address. makelisten() then creates an internet family SOCK_STREAM socket, which by definition is a TCP socket, but you specify this explicitly anyway, as in makeconn().

In line 18, the socket is bound to a local address. This tells the system that any messages sent to the specified service port and internet address should be relayed to the specified socket. You use sockaddr_in() to build an address from the service port retrieved with getportbyname() and with a special address that corresponds to all addresses on the workstation so that connections can be made to all network interfaces and even over any dial-up interfaces on the workstation. This function shows a little laziness in that it passes the sockaddr_in() function to bind() instead of calling it separately and saving the results.

There are some restrictions on what service ports can be bound. For historical reasons, only the programs executing with superuser access can bind service ports numbered lower than 1024.

After the socket is bound, you can execute listen(), which notifies the system that you're ready to accept client connections.

server1, the program that uses makelisten(), is just as simple as the client and is shown in Listing 28.5. You can find it on the CD-ROM that accompanies this book.

Listing 28.5. server1.

#!/usr/bin/perl

  use Socket;

  require "./network.pl";



  $hello = "Hello world!";



  $LISTFD = makelisten("test");

Previous | Table of Contents | Next