Chapter 12

Using Sockets


CONTENTS


Perl offers a host of functions for accessing the socket-based interprocess communication facilities. The system facilities on UNIX systems are available to the Perl programmer and, thus, can be called directly from Perl scripts. Given the information in this chapter, you should be able to write your own client/server Perl applications using sockets.

A Very Brief Introduction to Sockets

Perl offers a host of functions for accessing the socket functions on a UNIX-based system. It's essential to cover some of the important features of interprocess communications in order to understand how the model fits in with Perl. Given the limited amount of space in a chapter, I cannot hope to possibly cover all the bases for socket programming. However, I will cover the basics, and you should have enough information from this chapter to develop your own client/server model using Perl.

The absolutely best reference to doing anything with network programming is UNIX Network Programming by W. Richard Stevens (Prentice Hall, ISBN 0-13-949876-1). The book provides programs and C code samples in excruciating detail that cover all aspects of network programming. BSD UNIX gives many ways to open, use, and close sockets, and this book covers them all. The examples presented in this chapter are derived from the C code in this book. Perl is great in that often you can do a line-by-line mapping of cookbook socket and network function calls in C to equivalent calls in Perl. (Someone ought to write an interpreter!) Please refer to Stevens's book for a more detailed discussion on internetworking with sockets.

In general, socket programming is based on the client/server model. A client is a program that makes requests to the server to get responses. A server is simply another program that responds to these requests. The server either can reside on the same computer as the client or can be a computer somewhere on a connecting network. Sending requests and receiving replies to transfer the data between clients and servers is the protocol with which they communicate.

A common protocol in the UNIX world is the TCP/IP protocol. The Internet Protocol (IP) handles the transfer of data from one computer to another over a network. The Transport Control Protocol (TCP) offers a set of reliability and connection functions that IP does not offer. Messages sent via TCP/IP from one computer are acknowledged by the other computer. The acknowledgment of sent messages increases reliability, but at the cost of efficiency. The User Datagram Protocol (UDP) is like TCP in sending messages, but has no acknowledge feature as such. This makes UDP faster when receiving acknowledgments is not as high of a priority as sending acknowledgments back. UDP tends to be less reliable than TCP because the sender UDP does not have a guarantee that the sent message even made it to the remote site. Think of UDP as the regular U.S. Mail service and TCP/IP as a registered letter service. Although the U.S. Mail is generally very reliable, a sender does not really know if the recipient did indeed receive the letter. As far as you are concerned, the letter got to its destination, and if it didn't the recipient will request another. This is similar to UDP. Send a message, and if it doesn't make it over to the destination-no problem-the recipient will ask again. When sending important documents though, you would most likely want to get a confirmation from the recipient. In this case, you'd normally use a registered letter service, which will return a signed receipt. The signed receipt is your "acknowledgment" in TCP/IP.

Most applications using TCP or UDP have a port number that they talk on to get the service they want. A machine assigns one unique port number to an application. Port numbers are standardized enough to identify the type of service being used. On UNIX systems, the file /etc/services maintains a list of services offered on each port. Port numbers between 1 and 255 are reserved for standard, well-known applications. There are well-known port numbers that everyone recognizes: for example, port 80 for the World Wide Web's server daemons, the nameserver on port 42, sendmail at port 25, and so on. In all cases, avoid using socket 0, since it's interpreted differently on different systems.

Two computers talk to each other via a network circuit. Each circuit is uniquely identified by a combination of two numbers called a socket. Basically a socket is the IP address of the machine plus the port number used by the TCP software.

There are two ways of defining the address: If two processes talking to each other are on the same machine, the "family" of protocols is referred to as AF_UNIX. If the communicators are on different machines, this is referred to as the AF_INET family. In the AF_UNIX family, sockets are assigned a pathname in the directory tree. In the AF_INET family, they are assigned a port number and application number. Using AF_INET, you can talk to processes on the same machine, but AF_UNIX is reserved for the same machine.

There are two types of sockets about which you should know:

There is a socket on both the sending and receiving machine. Clients send on their sockets, and servers listen on their sockets and accept connections when necessary. The IP address of each machine is guaranteed to be unique by design, and the port numbers are unique to each machine. This implies the socket numbers, which are a combination of these two unique numbers, will also be unique across the network. This allows two applications to communicate using unique socket numbers.

With Perl, it's possible to get access to these socket and network functions. Most of this chapter has a UNIX slant to it. On NT machines, you'll be dealing with the Remote Access Server and WinSock under Windows. Please refer to the technical notes from Microsoft for more information on WinSock programming.

Perl Functions for Working with Protocols

The protocols available on your UNIX system are located in the /etc/protocols file. You have to use three functions to read this file. The function setprotoent() starts the listing process. The Perl function getprotoent() reads one line from the /etc/protocols file and lists it for you. Successive calls to the function read successive lines. Finally, a call to endprotoent() stops the listening process. A simple way to have all the protocols available to your Perl script is to use the script shown in Listing 12.1.


Listing 12.1. Showing available protocols.
1 #!/usr/bin/perl
2 #
3 # List all the protocols in this machine
4 #
5 setprotoent(1);
6 while (($name, $aliases, $protonum) = getprotoent) {
7      print " Name=$name, Aliases=$aliases, Protocol=$protonum \n";
8 }
9 endprotoent;

The output should be similar to what is shown here:

Name=ip, Aliases=IP, Protocol=0
Name=icmp, Aliases=ICMP, Protocol=1
Name=igmp, Aliases=IGMP, Protocol=2
Name=ggp, Aliases=GGP, Protocol=3
Name=tcp, Aliases=TCP, Protocol=6
Name=pup, Aliases=PUP, Protocol=12
Name=udp, Aliases=UDP, Protocol=17
Name=idp, Aliases=IDP, Protocol=22
Name=raw, Aliases=RAW, Protocol=255

To keep the file open between successive calls to the getprotoent() call, you should call the setprotoent() function with a nonzero parameter. To stop querying the file, use the endprotoent() call.

To determine whether you have a specific protocol present, you can use the system call getprotobyname or getprotobynumber. A return value of NULL indicates that the protocol is not there. The name passed to the function is not case-sensitive. Therefore, to list the names, aliases, and the protocol number for TCP, you can use this:

if  (($name, $aliases, $protonum) = getprotobyname('tcp')) {
     print "\n Name=$name, Aliases=$aliases, Protocol=$protonum";
}
print "\n"

A comparable set of calls is available for determining what services are available for your machine. This call queries the /etc/services file. Listing 12.2 illustrates how to use these calls. The setservent call with a nonzero file rewinds the index into the services file for you, the getservent gets the four items in the service entry, and the endservent call terminates the lookup. The output from this file can be a bit lengthy and is shown in Listing 12.2 starting at line 15.

In Listing 12.2, lines 1 and 2 clear the screen and show the output of the showme.pl file with the script in it. At line 13, we execute this script. Your output may be different than the one shown in Listing 12.2 depending on what services you have installed on your system.


Listing 12.2. Listing server services.
  1 $ clear
  2 $ cat showme.pl
  3 #!/usr/bin/perl
  4 setservent(1);
  5 printf "%15s %15s %4s %15s\n",
  6     "Name","Aliases","Port","Protocol";
  7 while(($nm,$al,$pt,$pr) = getservent) {
  8     # print "Name=$nm, Aliases=$al, Port=$pt, $Protocol=$pr\n";
  9     printf "%15s %15s %4d %15s\n", $nm,$al,$pt,$pr;
 10 }
 11 endservent;
 12 $
 13 $
 14 $ showme.pl
 15            Name         Aliases          Port         ;Protocol
 16          tcpmux                             1             tcp
 17            echo                             7             tcp
 18            echo                             7             udp
 19         discard       sink null             9             tcp
 20         discard       sink null             9             udp
 21          systat           users            11             tcp
 22         daytime                            13    ;          tcp
 23         daytime                            13    ;          udp
 24         netstat                            15    ;          tcp
 25            qotd           quote            17             tcp
 26             msp                            18             tcp
 27             msp                            18             udp
 28         chargen   ttytst source            19             tcp
 29         chargen   ttytst source            19             udp
 30             ftp                            21             tcp
 31          telnet                            23              tcp
 32            smtp            mail            25   &nbs p;         tcp
 33            time       timserver            37             tcp
 34            time       timserver            37             udp
 35             rlp        resource            39             udp
 36      nameserver            name            42        &nbs p;    tcp
 37           whois         nicname            43             tcp
 38          domain      nameserver            53          &n bsp;  tcp
 39          domain      nameserver            53          &n bsp;  udp
 40             mtp                            57             tcp
 41          bootps                            67              tcp
 42          bootps                            67              udp
 43          bootpc                            68              tcp
 44          bootpc                            68              udp
 45            tftp                            69&n bsp;            udp
 46          gopher                            70              tcp
 47          gopher                            70              udp
 48             rje          netrjs            77             tcp
 49          finger                            79              tcp
 50             www            http            80             tcp
 51             www                            80             udp
 52            link         ttylink            87      & nbsp;      tcp
 53        kerberos            krb5            88              tcp
 54        kerberos                            88   &nbs p;         udp
 55          supdup                            95              tcp
 56       hostnames        hostname           101             tcp
 57        iso-tsap            tsap           102             tcp
 58        csnet-ns          cso-ns           105             tcp
 59        csnet-ns          cso-ns           105             udp
 60         rtelnet                           107   &nbs p;         tcp
 61         rtelnet                           107   &nbs p;         udp
 62            pop2      postoffice           109             tcp
 63            pop2                           109 & nbsp;           udp
 64            pop3                           110 & nbsp;           tcp
 65            pop3                           110 & nbsp;           udp
 66          sunrpc                           111    ;          tcp
 67          sunrpc                           111    ;          udp
 68            auth tap ident authentication  113             tcp
 69            sftp                           115 & nbsp;           tcp
 70       uucp-path                           117             tcp
 71            nntp   readnews untp           119             tcp
 72             ntp                           123             tcp
 73             ntp                           123             udp
 74      netbios-ns                           137      & nbsp;      tcp
 75      netbios-ns                           137      & nbsp;      udp
 76     netbios-dgm                           138             tcp
 77     netbios-dgm                           138             udp
 78     netbios-ssn                           139             tcp
 79     netbios-ssn                           139             udp
 80           imap2                           143             tcp
 81           imap2                           143             udp
 82            snmp                           161 & nbsp;           udp
 83       snmp-trap        snmptrap           162             udp
 84        cmip-man                           163    &nb sp;        tcp
 85        cmip-man                           163    &nb sp;        udp
 86      cmip-agent                           164      & nbsp;      tcp
 87      cmip-agent                           164      & nbsp;      udp
 88           xdmcp                           177             tcp
 89           xdmcp                           177             udp
 90        nextstep NeXTStep NextStep         178             tcp
 91        nextstep NeXTStep NextStep         178             udp
 92             bgp                           179             tcp
 93             bgp                           179             udp
 94        prospero                           191    &nb sp;        tcp
 95        prospero                           191    &nb sp;        udp
 96             irc                           194             tcp
 97             irc                           194             udp
 98            smux                           199 & nbsp;           tcp
 99            smux                           199 & nbsp;           udp
100         at-rtmp                           201    &nb sp;        tcp
101         at-rtmp                           201    &nb sp;        udp
102          at-nbp                           202   &nbs p;         tcp
103          at-nbp                           202   &nbs p;         udp
104         at-echo                           204    &nb sp;        tcp
105         at-echo                           204    &nb sp;        udp
106          at-zis                           206   &nbs p;         tcp
107          at-zis                           206   &nbs p;         udp
108           z3950            wais           210             tcp
109           z3950            wais           210             udp
110             ipx                           213             tcp
111             ipx                           213             udp
112           imap3                           220             tcp
113           imap3                           220             udp
114       ulistserv                           372             tcp
115       ulistserv                           372             udp
116            exec                           512              tcp
117            biff          comsat           512             udp
118           login                           513             tcp
119             who            whod           513             udp
120           shell             cmd           514             tcp
121          syslog                           514   &nbs p;         udp
122         printer         spooler           515             tcp
123            talk                           517              udp
124           ntalk                           518             udp
125           route   router routed           520             udp
126           timed      timeserver           525             udp
127           tempo         newdate           526             tcp
128         courier             rpc           530             tcp
129      conference            chat           531             tcp
130         netnews        readnews           532             tcp
131         netwall                           533    &nb sp;        udp
132            uucp           uucpd           540             tcp
133        remotefs  rfs_server rfs           556             tcp
134          klogin                           543   &nbs p;         tcp
135          kshell                           544   &nbs p;         tcp
136    kerberos-adm                           749        &nbs p;    tcp
137         webster                           765    &nb sp;        tcp
138         webster                           765    &nb sp;        udp
139      ingreslock                          1524         ;     tcp
140      ingreslock                          1524         ;     udp
141     prospero-np                          1525             tcp
142     prospero-np                          1525             udp
143             rfe                          5002             tcp
144             rfe                          5002             udp
145       krbupdate            kreg           760             tcp
146         kpasswd            kpwd           761             tcp
147         eklogin                          2105     &n bsp;       tcp
148      supfilesrv                           871              tcp
149      supfiledbg                          1127         ;     tcp

Tip
The gethostent function was not implemented as of Perl 5.002.

Perl also lets you look at the host name by address in your /etc/hosts file with the gethostbyaddr call. This function takes two parameters, the address to look up and the value of AF_INET. On most systems, this value is set to 2 but can be looked up in the /usr/include/sys/socket.h file. The gethostbyname("hostname") function returns the same values as the gethostbyaddr() call. The parameter passed into the function is the name of the host being looked up. Listing 12.3 illustrates how to do this.

In the program shown in Listing 12.3, the code in Line 4 gets the host name and alias given the address 204.251.103.2. You would use a different address, of course, because the address shown here is specific to my machine. Lines 6 through 10 print the components of the information you get back from the gethostbyaddr function call. Also, in lines 12 and 13, you can get the same information back using the node name instead of an IP address. Lines 14 through 19 print these values.


Listing 12.3. Sample listing to show usage of gethostbyname and gethostbyaddr.
 1 #!/usr/bin/perl
 2
 3 $addr = pack('C4',204,251,103,2);
 4 ($name,$alias,$atype,$len,@addrs) = gethostbyaddr($addr,2);
 5 ($a,$b,$c,$d) = unpack('C4',$addrs[0]);
 6 print "Name :  $name \n";
 7 print "Alias:  $alias \n";
 8 print "Type :  $atype \n";
 9 print "Len  :  $len \n";
10 print "Node :  $a.$b.$c.$d \n";
11
12 $name = "www.ikra.com";
13 ($name,$alias,$atype,$len,@addrs) = gethostbyname($name);
14 ($a,$b,$c,$d) = unpack('C4',$addrs[0]);
15 print "Name :  $name \n";
16 print "Alias:  $alias \n";
17 print "Type :  $atype \n";
18 print "Len  :  $len \n";
19 print "Node :  $a.$b.$c.$d \n";

Note
Note the use of the number 2 in the call to gethostbyaddr in Listing 12.3. This should be the constant $AF_INET.

Socket Primitives

Enough already about getting information on your system. Let's see what socket functions are available to you. Depending on your site and what extensions you have for Perl, you may have more functions available. Check the man pages for socket for more information. Here are the most common ones you'll use:

I cover these functions in the following sections. However, there are some constants that must be defined before I continue. These constants are used in all function calls and scripts in this chapter. Feel free to change them to reflect your own system's peculiarities. Here's a list of the constants:

socket()

The socket() system call creates a socket for the client or the server. The socket function is defined as this:

socket(SOCKET_HANDLE, $FAMILY, $TYPE, $PROTOCOL);

The return value from this function is NULL, and if there was an error, you should check the $! for the type of error message. The call to open a socket looks like this:

socket(MY_HANDLE,  $AF_UNIX, $STREAMS, $PROTOCOL) ||
     die "\nCannot open socket: $!\n";
print "\nSocket successfully opened\n";

It's a good idea to unlink any existing file names for previously opened sockets with the unlink call:

unlink "$my_tst_srvr" || die "\n$O: No permissions";

You'll use the socket descriptor MY_HANDLE to refer to this socket in all subsequent network function calls in your program. Sockets are created without a name. Clients use the name of the socket in order to read or write to it. This is where the bind function comes in.

The bind() System Call

The bind() system call assigns a name to an unnamed socket:

bind(SOCKET_HANDLE, $nameAsAString);
bind(SOCKET_HANDLE, $sockaddr);

The first item is the socket descriptor you just created. The second parameter is the name that refers to this socket if you are using AF_UNIX or its address if you are using AF_INET.

The call to bind using AF_UNIX looks like this:

bind(MY_HANDLE,"./mysocket") || die "Cannot bind $!\n";

In AF_INET, it looks like this:

$port = 6666
$AF_INET=2;     # Use AF_INET instead of AF_UNIX
($name,$alias,$atype,$len,$addr)=gethostbyname(`uname -n`);
$my_ip_addr = pack(S n C4 x8,$AF_INET,$STREAMS,$port,$addr);
bind(MY_HANDLE,$my_ip_addr) || die "Cannot bind $!\n";

The parameters' pack() function probably needs some explanation. The pack() function takes two parameters: a list of formats to use and a list of values to pack into one continuous stream of bytes. In our case, the bind() call expects a sockaddr structure of the following form in a C structure:

{
unsigned short family;
int network;
long     address;
char nullbytes[8];
     }

The first parameter to the pack instruction can take the values listed in Table 12.1. Check the man pages for the pack instruction for more details. You had the pack instruction create the socket address structure for you. Therefore, the script uses S n C4 x8 to pack a signed short, followed by an integer in network order, four unsigned characters, and eight NULL characters to get this call:

pack(S n C4 x8,$AF_INET,$STREAMS,$port,$addr);

Table 12.1. The types of packing supported by pack().
Character
Type of Packing
@
Null fill to absolute position
a
An ASCII string, padded with NULLs
A
An ASCII string, padded with spaces
b
A bit string in ascending bit order
B
A bit string in descending bit order
c
A signed char value
C
An unsigned char value
d
A double-precision float in the native format
f
A single-precision float in the native format
H
A hex string, high nibble first
h
A hex string, low nibble first
i
A signed integer value
I
An unsigned integer value
l
A signed long value
L
An unsigned long value
N
A long in network order
n
A short in network order
p
A pointer to a null-terminated string
P
A pointer to a structure (fixed-length string)
s
A signed short value
S
An unsigned short value
u
A uuencoded string
V
A long in little-endian order
v
A short in little-endian order
x
A null byte
X
Back up a byte

Now that you have bound an address for your server or client, you can connect to it or listen for connections with it. If your program is a server, it will set itself up to listen and accept connections.

Tip
Do not use S n A4 x8 instead of S n C4 x8 for packing into the sockaddr structure. The C4 specifies four unsigned char data values and is safe to use. The A4 implies a string, which may confuse the pack() function if there are nulls (zeroes) in the address.

Now let's look at the functions available for use in a server.

The listen() and accept() System Calls

The listen() system call is used by the server to listen for connections. Once it is ready to listen, the server is able to honor any requests for connections with the accept system call. The listen call is defined as this:

listen(SOCKET_HANDLE, $queueSize);

The SOCKET_HANDLE is the descriptor of the socket you created. The queueSize is the number of waiting connections allowed at one time before any are rejected. Use the standard value of 5 for queue size. A returned value of NULL indicates an error. The call to listen normally looks like this:

listen(MY_HANDLE,5) || die "Cannot listen $!\n";

If this call is successful, you can accept connections with the accept function, which looks like this:

accept(NEWSOCKET, ORIGINAL_SOCKET);

The accept() system call is used by the server to accept any incoming messages from a client's connect() calls. Be aware that this function will not return if no connections are received. As requests come off the queue and set up in the listen() call, the accept function handles them by assigning them to a new socket. NEWSOCKET is created by the accept function as ORIGINAL_SOCKET, but now NEWSOCKET is going to be used to communicate with the client. At this point, most servers fork off (fork()) a child process to handle the client and go back to wait for more connections. Before I get into that, let's see how connections are originated.

Let's look at the connect() call that you'll use to connect to a server.

The connect() System Call

The connect() system call is used by clients to connect to a server in a connection-oriented system. This connect() call should be made after the bind() call. There are two ways you can call the connect() call: one for AF_UNIX using the pathname of the socket and the other using an address as the AF_INET requirement for a socket handle.

connect(SOCKET_HANDLE,"pathname" ); # for AF_UNIX
connect(SOCKET_HANDLE,$Address); # for AF_INET

Connection-Oriented Servers in Perl

Given this background information about socket information gathering, creation, and so on, you are now ready to write your own server using Perl. Listing 12.4 presents a sample server.


Listing 12.4. Server side for connection-oriented protocol.
 1 #!/usr/bin/perl
 2 #
 3 # Sample connection oriented server using Perl
 4 #
 5 $AF_UNIX = 1;
 6 $AF_INET=2;     # Use AF_INET instead of AF_UNIX.
 7 $SOCK_STR = 1;  # Use STREAMS.
 8 $PROTOCOL = 0;  # stick to the default protocols (IP).
 9
10 $port = 6668 unless $port;
11
12 #
13 # The pattern for packing into a sockaddr structure
14 #
15 $PACKIT='S n C4 x8';
16
17 #
18 # Disable any buffering on any newly created sockets.
19 #
20 select(NEWSOCKET);
21 $| = 1;
22 select(stdout);
23
24 #
25 # Create the socket.
26 #
27 socket(MY_SOCKET, $AF_INET, $SOCK_STR, $PROTOCOL) ||
28                        die "\n $0: Cannot open socket: $!";
29 print "Socket successfully opened\n";
30
31 #
32 # Get the host address for this node
33 #
34
35 ($name, $aliases, $addrtype, $len, @addrs) = gethostbyname("www.ikra.com");
36 ($a,$b,$c,$d) = unpack('C4',$addrs[0]);
37 print "Server Name=$name, Server Address= $a.$b.$c.$d\n";
38 $my_ip_addr = pack($PACKIT,$AF_INET,$port,$addrs[0]);
39
40 #
41 # If you just want to test with the localhost, try this line
42 # instead of the above.
43 # $my_ip_addr = pack($PACKIT,$AF_INET,$port,127,0,0,1);
44
45 #
46 # Bind to the socket and listen on this port
47 #
48 bind(MY_SOCKET, $my_ip_addr) || die "$0: Cannot bind .. $!\n";
49 print  "\n Bound to socket";
50 listen(MY_SOCKET,5)  || die "$0: Cannot listen: $!\n";
51 print  "\n Listening \n";
52
53 while(1) {
54      $remote = accept(NEWSOCKET, MY_SOCKET) || die "$0: Unacceptable: $!\n";
55
56 #
57 # In case you have to display incoming connection
58 # information, you can uncomment the next three lines of code:
59
60 #         @remoteInfo = unpack($PACKIT,$remote);
61 #         $, = ' ';
62 #         print @remoteInfo; print "\n";
63
64      # $pid = fork || &cleanup;
65
66           if ($pid == fork)  {  # child
67           sleep 3;
68           print NEWSOCKET "Welcome to this server\n";
69           # in child,.. you can do other stuff here.
70           close NEWSOCKET;
71           # I chose to just print this message and terminate
72           close MY_SOCKET;
73           exit;
74      }
75      else {  # parent
76           sleep 10;
77           close MY_SOCKET;
78           close NEWSOCKET;  # in parent
79           exit;
80      }
81
82 }
83 sub cleanup { close NEWSOCKET; close(MY_SOCKET); die "$0: Cannot fork : $!\n"; }

Note
Of course, instead of the IP addresses shown above in Listing 12.4, you would have to modify the Perl script to use your own machine name and IP address. Do not use the addresses shown in this example because they are coded to work with a specific machine with a specific name.

In the case of connection-oriented protocols, the server does the following functions:

Once a connection to the server has been accepted, the client and server can exchange data with the read() and write() function calls. To read from the socket, use the function call

read(MY_SOCKET, $buffer, $length);

where SOCKET_HANDLE is the socket you are reading from and $buffer is where you will be putting in data of size $length. To write to the socket, you can use the function call

write(MY_SOCKET, $buffer, $length);

For sending just text data, you can use the print call instead. For example, the following code will write text to the socket:

print MY_SOCKET, "Hello, ..";

Once a connection has served its time, it has to be closed so that other clients are able to use the system resources. To close the socket, your server and clients should call the close() function:

close(MY_SOCKET);

The shutdown() function allows you to selectively shut down sends and receives on a socket. Here's the function call:

shutdown(MY_SOCKET,HOW);

When the HOW parameter is 0, no more data is received on this socket. If HOW is set to 1, no more data will be sent out on this socket. If set to 2, no data is received or sent on this socket. (You still have to close the socket, even if you shut it down for sending and receiving.)

Listing 12.5 presents a sample of the client side of things.


Listing 12.5. The client side.
 1 #!/usr/bin/perl
 2 #
 3 # define constants for talking to server
 4 #
 5 $PACKIT = 'S n C4 x8';
 6 $AF_INET = 2;
 7 $SOCK_STR = 1;     # STREAMS
 8 $DEF_PROTO = 0;    #default protocol of IP
 9 $port = 6668 unless $port;
10
11 #
12 # Get the name of the server
13 #
14 ($name, $aliases, $addrtype, $len, @addrs) = gethostbyname("www.ikra.com");
15 ($a,$b,$c,$d) = unpack('C4',$addrs[0]);
16 print "Server Name=$name, Server Address= $a.$b.$c.$d\n";
17 $that = pack($PACKIT,$AF_INET,$port,$addrs[0]);
18
19 #
20 # Confine yourself to the local host machine address of 127.0.0.1
21 #
22 $this = pack($PACKIT,$AF_INET,$port,127,0,0,1);
23
24 #
25 # Disable buffering on this socket.
26 #
27 select(CLIENT_SOCKET);
28 $| = 1;
29 select(stdout);
30
31
32 socket(CLIENT_SOCKET,$AF_INET,$SOCK_STR,$DEF_PROTO) ||
33      die "$0: Cannot open socket\n";
34 print "Created socket\n";
35
36 #
37 # Attempt to connect to server.
38 #
39 do
40 {
41  sleep(1);
42  $result = connect(CLIENT_SOCKET,$that);
43  if (result != 1) {
44      print "Sleeping\n";
45      }
46
47 } while ($result != 1);
48
49 sleep(5);
50 print "After connection\n";
51
52 #
53 # send data to server
54 #
55 # write(CLIENT_SOCKET,"hello",5);
56
57 read(CLIENT_SOCKET,$buf,100);
58
59 print "[" . $buf . "]\n";
60 close(CLIENT_SOCKET);

The client for connection-oriented communication also takes the following steps:

Tip
After the connection is used up by the client, it's a good idea to close the socket so that others may use the system resources.

That's about it for a client program. Any processing that has to be done is done while the connection is open. Client programs can be written to keep a connection open for a long time while large amounts of data are transferred. If there is too long of a delay between successive messages, clients would then open a socket connection, send the message or messages, and close the connection immediately after the acknowledgment, if any, arrives. This way, all sockets are opened only on an as needed basis and do not use up socket services when both the server and client are idle.

The h2ph Script

If you read more documentation on Perl and sockets, you'll see references to the socket.ph file. If you cannot find this file anywhere on your system, it's because you have not run the h2ph file on your include directories. This h2ph program converts C header files to Perl header files. The safest way to ensure that you have all the files converted to Perl headers is to issue the following statements while logged in as root:

$ cd /usr/include
$ h2ph *
$ h2ph sys/*

You may run into some problems while running this script. For instance, it will say that it's creating a .ph file from a .h file, but after execution, the *.ph file may not exist! Check the script in the h2ph file to see where $perlincl is pointing and if you have read/write permissions there. A common repository is the /usr/local/lib/perl5 or the /usr/lib/perl5 directory. Another thing to remember is that the @Inc variable in your Perl scripts should point to the same location where the *.ph files are placed.

Using Socket.pm

The standard Perl 5 distribution comes with the Socket.pm module, which greatly speeds up Perl code development work. Look at the documentation in the /usr/lib/Perl5/Socket.pm file for more information. This module requires dynamic loading, so ensure that your system supports it.

Summary

Perl offers very powerful features for using sockets on UNIX machines. The system calls available offer enough power and flexibility to create client/server applications in Perl without having to write code in a compiled language.

The functions available in Perl include those for querying available system services and protocols, IP addresses, and other host name information. Here are a few key points to remember when working with Perl and sockets: