Networking API for Perl

 < Day Day Up > 



Perl includes multiple levels for Sockets access. At the bottom is the Socket module, which provides direct access to the native Sockets libraries on the host operating system. A higher-level module, IO::Socket, provides a mechanism for simplifying the creation of sockets. Finally, optional APIs are available for higher-level Application layer protocols, such as HTTP, FTP, SMTP, Telnet, and even CGI support.

The native socket module provides an API identical to that of the BSD standard API (see Figure 12.1). The IO::Socket and IO::Socket::INET (see Figure 12.2) provide a single constructor, new, as well as a number of methods (in the object-oriented sense). We discuss each of these shortly.

start figure

Function

Purpose

accept clientsocket, serversocket

Accept a new client socket from a server socket.

bind socket, localname

Bind the localname to the socket.

connect socket, name

Connect the socket to name.

getpeername socket

Get the socket address for the remote peer.

getsockname socket

Get the socket address for the local socket.

getsockopt socket, level, opname

Get the value of a socket option.

setsockopt socket, level, optname, optval

Set the value for a socket option.

listen socket, backlog

Enable accepting incoming client connections.

recv socket, scalar, length, flags

Receive a message from a socket.

send socket, msg, flags [,to]

Send a message to a socket.

shutdown socket, how

Shut down a socket.

socket socket, domain, type, protocol

Create a new socket of the defined type.

close socket

Close the socket.

end figure

Figure 12.1: Perl Sockets functions.

start figure

Function

Type

Purpose

new

Class

Creates a new IO::Socket::INET object.

sockaddr

Method

Return the socket local socket address.

sockport

Method

Return the socket local port.

sockhost

Method

Return the socket local socket address string.

peeraddr

Method

Return the peer socket address.

peerport

Method

Return the peer socket port.

peerhost

Method

Return the peer socket address string.

end figure

Figure 12.2: Perl IO::Socket::INET capabilities.

Sockets API Discussion

Let's now look at how the Perl Sockets API is used. We'll exercise many of the functions shown in Figure 12.1, including how using functions IO::Socket and IO::Socket::INET can simplify the creation of sockets.

Creating and Destroying Sockets

As with any socket-based application, the creation of a socket is the first step before communication may occur. Perl provides a number of ways in which a socket can be created. We look at the primitive example first, and then move on to Perl's more expressive methods that can simplify socket creation.

Note 

All of the methods discussed in this section require that the application developer make the sockets module visible. At the beginning of the perl script, a line specifying, 'use Socket' must be present. For object interfaces (IO::Socket::INET), 'use IO::Socket::INET' must be present.

The Socket module provides the primitive standard socket function that is most familiar to C language programmers. This class method can be used to create stream (TCP), datagram (UDP), and raw sockets.

 socket( myStreamSock, Socket::AF_INET, Socket::SOCK_STREAM, 0 );

Note the similarities of this function to the C language primitive. The only real differences are the Perl naming conventions (SOCKET:: to bring the symbol in scope). In this example, we've created a stream socket. To create a datagram socket, we could do the following:

 socket( myDgramSock, Socket::AF_INET, Socket::SOCK_DGRAM, 0 );

Finally, a raw socket could be created with:

 socket( myRawSock, Socket::AF_INET, Socket::SOCK_RAW, 0 )

Recall that the Socket::AF_INET symbol defines that we're creating an Internet protocol socket. The second argument (type) defines the semantics of the communication (Socket::SOCK_STREAM for TCP, Socket::SOCK_DGRAM for UDP, and Socket::SOCK_RAW for raw IP). The third argument defines the particular protocol to use, which is useful here only in the Socket::SOCK_RAW case.

Sockets can also be created using the IO::Socket::INET module. This module contains a constructor, new, that is used to create sockets with very specific parameters. For example, rather than calling socket and then bind to bind a local address, the IO::Socket::INET->new function can create the socket and perform the bind in one operation. This simplifies the socket creation process. Additionally, socket options can also be applied (such as the ReuseAddr parameter, which provides the SO_REUSEADDR socket option). The available parameters for the IO::Socket::INET new constructor are shown in Figure 12.3.

start figure

Key

Purpose

PeerAddr

Remote address.

PeerPort

Remote port.

PeerHost

Remote host address.

LocalAddr

Local address.

LocalPort

Local port.

LocalHost

Local host address.

Proto

Protocol (name or number).

Type

Socket type.

Listen

backlog queue length.

ReuseAddr

Allow local reuse of the address.

Timeout

Timeout value for certain operations.

MultiHorned

Attempt to use all local interfaces.

Blocking

Enable blocking mode.

end figure

Figure 12.3: Options for IO::Socket::INET->new constructor.

Let's now look at a few examples of IO::Socket::INET to see how it can be used. In the first example, we simply create a stream socket and automatically connect to a peer:

use IO::Socket::INET; $sock = IO::Socket::INET->new( PeerAddr => '192.168.1.1',                                  PeerPort => 25,                                  Proto    => 'tcp' ); 

In this case, the $sock represents a new client socket that has been connected to the host identified by IP address ‘192.168.1.1', port 25 using the TCP protocol. Let's now look at a server socket creation example using the same constructor:

use IO::Socket::INET; $sock = IO::Socket::INET->new( LocalAddr => '192.168.1.1',                                  LocalPort => 25,                                  Listen    => 5,                                  Proto     => 'tcp' );

In this example, the local address and port keys specify to what the new socket will be locally bound. The Listen key defines the backlog queue length (as is typical with the listen call), and, finally, Proto defines the protocol that we want to use, in this case TCP.

When we're finished with a socket, we must close it. To close our previously created socket, $sock, we use the close operator.

close $sock

Once the close method is called, no further communication is possible with this socket.

Any data queued for transmission would be given some amount of time to be sent before the connection physically closes. The shutdown operator is used as follows:

shutdown( $sock, 0 );

# No further reading possible

shutdown( $sock, 1 );

# No further writing possible

shutdown( $sock, 2 );

# No further use of this socket

The IO::Socket::INET object can also use shutdown in the following manner:

$sock->shutdown( 2 );

# No further use of this socket

Socket Addresses

Like C, Perl has the concept of a sockaddr_in structure and a set of associated functions. Recall that the sockaddr_in structure contains not only an address (32-bit IPv4 address), but also a 16-bit port value.

Consider the following C language fragment:

struct sockaddr_in sa; sa.sin_family = AF_INET; sa.sin_port = htons( 13 ); sa.sin_addr.s_addr = inet_addr("192.168.1.2");

This creates a sockaddr_in structure and fills it in with IP address '192.168.1.2' and port 13 (using the AF_INET family). Consider this synonymous code fragment from Perl:

use Socket; ... my $addr = inet_aton( "192.168.1.2" ); my $paddr = sockaddr_in( 13, $addr );

We first convert the dotted-notation string IP address using inet_aton (as was done in C with inet_addr) and then use this to create the packed address using sockaddr_in. The port number is provided (13) resulting in the packed address $paddr.

Given a packed address (such as $paddr in the previous example), we can extract the address and port elements as shown in the following code snippet:

( $myport, $myaddr ) = sockaddr_in( $paddr ); print "The port is ", $myport, "\n"; print "The IP address is ", inet_ntoa( $myaddr ), "\n";

Using C-style structures as sockaddr_in makes it easy for C programmers to build Perl scripts, but because Perl also provides simpler methods, understanding the C address paradigm is not necessary.

Socket Primitives

In this section, we look at a number of other important socket control methods. We also investigate the variety of ways that the same results can be achieved using different Perl methods.

Bind

The bind method provides a local naming capability to a socket. This can be used to name either client or server sockets, but is used most often in the server case. The bind function is provided as follows:

use Socket; socket( mySock, Socket::AF_INET, Socket::SOCK_STREAM, 0 ); my $port = 25; my $addr = inet_aton( "192.168.1.1" ); my $paddr = sockaddr_in( $port, $addr ); bind( mySock, $paddr );

where $paddr is a packed address of '192.168.1.1', port 25. The same thing could be accomplished using the IO::Socket::INET, as:

$mySock = IO::Socket::INET->new( LocalAddr => '192.168.1.1',                                    LocalPort => 25,                                    Proto     => 'tcp',                                    Listen    => 5 );

In this example, we're creating a stream server on port 25 that will accept client connections only on the interface defined as ‘192.168.1.1'. Note also in this example that the listen function is also called, which was not performed in the prior example.

If we want to accept client connections from any available interface, we could bind to INADDR_ANY. This behavior is synonymous to the INADDR_ANY symbolic within our C language examples, for instance:

use Socket; socket( mySock, Socket::AF_INET, Socket::SOCK_STREAM, 0 ); my $port = 25; my $paddr = sockaddr_in( $port, INADDR_ANY ); bind( mySock, $paddr );

Note that we could also pass a 0 as the port to allow the networking layer to dynamically assign us a port (ephemeral port).

Finally, let's look at a UDP example. The following example creates a UDP socket and binds it with host INADDR_ANY (accept datagrams from any interface) with port 13:

use Socket; socket( mySock, Socket::AF_INET, Socket::SOCK_DGRAM, 0 ); my $port = 13; my $paddr = sockaddr_in( $port, INADDR_ANY ); bind( mySock, $paddr );

Listen

Before a server socket can accept incoming client connections, it must call the listen method to declare this willingness. The listen function is illustrated using the mySock TCP server socket:

 listen( mySock, backlog );

The mySock variable represents an instance of the server socket and the backlog argument represents the number of outstanding client connections that may be queued. This method may only be used on stream sockets. Here's a complete example from socket creation to the listen method.

use Socket; socket( mySock, Socket::AF_INET, Socket::SOCK_STREAM, 0 ); my $port = 25; my $addr = inet_aton( "192.168.1.1" ); my $paddr = sockaddr_in( $port, $addr ); bind( mySock, $paddr ); listen( mySock, 5 );

This is identical to the following code fragment as created with IO::Socket::INET:

$mySock = IO::Socket::INET->new( LocalAddr => '192.168.1.1',                                    LocalPort => 25,                                    Proto     => 'tcp',                                    Listen    => Socket::SOMAXCONN );

It should be clear from this example that the IO::Socket::INET constructor method provides not only server socket creation, but also local address binding and the listen call, thus simplifying the code considerably. Rather than specify an arbitrary backlog size, the maximum connections constant can be used instead, Socket::SOMAXCONN.

Accept

The accept method is the final call made by servers to accept incoming client connections. Before accept can be invoked, the server socket must be created, a name must be bound to it, and listen must be invoked. The accept function blocks and then returns a new client socket upon the client receiving a new incoming client connection. The following example illustrates a simple socket that accepts a new client socket and then writes a short message to it (acctest.pl).

The accept method in the Sockets class accepts a new client connection and returns an array containing the new client socket and the client address information (packed in a sockaddr_in string):

use Socket; socket( mySock, Socket::AF_INET, Socket::SOCK_STREAM, 0 ); my $paddr = sockaddr_in( 5300, INADDR_ANY ); bind( mySock, $paddr ); listen( mySock, Socket::SO_MAXCONN ); accept( cliSock, mySock ); print cliSock "Hello!\n"; close cliSock; close mySock;

In this example, the accept function returns a new client socket (cliSock), which is then used for further communication with the client. We could identify the source of the connection as follows:

$peer = getpeername cliSock; ($port, $ipaddr) = unpack_sockaddr_in( $peer ); print $port, "\n"; print inet_ntoa( $ipaddr ), "\n";

Connect

The connect function is used by client Sockets applications to connect to a server. Clients must have created a socket and then defined an address structure containing the host and port number to which they want to connect. This is illustrated (conntest.pl) by the following code segment (which can be used to connect to the previously illustrated accept method example):

use Socket; socket( mySock, Socket::AF_INET, Socket::SOCK_STREAM, 0 ); $addr = inet_aton( "127.0.0.1" ); $paddr = sockaddr_in( 5300, $addr ); connect( mySock, $paddr ); $line = <mySock>; print $line; close mySock;

We create our address structure $paddr (as with previous examples) and then pass this to our connect method using our client socket instance. We could also write this using IO::Socket::INET as (conntst2.pl):

use IO::Socket::INET; $mySock = IO::Socket::INET->new(             PeerAddr => '127.0.0.1',             PeerPort => 5300,             Type     => Socket::SOCK_STREAM ); $line = <$mySock>; print $line; close $mySock;

The connect method (for TCP) blocks until either an error occurs, or the three-way handshake with the server completes. For datagram sockets (UDP), the method binds the peer locally so that the peer address isn't required to be specified for every send.

Sockets I/O

A variety of API methods exists to read data from a socket or write data to a socket. Some functions are Socket module specific, and others are inherited from other modules. First, we look at reading and writing from connected sockets and then investigate unconnected (datagram-specific) socket communication.

A number of methods are provided to communicate through a socket. Some of the functions include recv, send, print, sysread, and syswrite. We will look at examples of each of these functions in the following sections. Other mechanisms can be used for input and output, but for the purposes of brevity, they won't be covered here.

Stream Sockets

Stream sockets can utilize all of the previously mentioned I/O methods. Datagram sockets must utilize methods that allow the specification of the recipient (for example, the send function). Let's now look at some sample code that illustrates the stream-specific methods. The first example illustrates a simple echo server:

use Socket; socket( srvSock, Socket::AF_INET, Socket::SOCK_STREAM, 0 ); $addr = inet_aton( '192.168.1.2' ); $paddr = sockaddr_in( 45000, $addr ); bind( srvSock, $paddr ); listen( srvSock, Socket::SO_MAXCONN ); while( true ) {     accept( cliSock, srvSock );     recv( cliSock, $line, 128, 0 );     print cliSock $line;     close cliSock; } close srvSock;

In this example, we create a new server socket using the socket function. We create a sockaddr_in structure representing IP address ‘192.168.1.2' and port 45000 and then bind ourselves to it. After listen, we accept a new client socket, read a line from it using recv, and then write the line back to the client using the print function. Finally, the client socket is closed with the close function, and then the loop repeats.

Now, let's look at the TCP client socket that will connect to the previously defined server:

use IO::Socket::INET; $sock = IO::Socket::INET->new(         PeerAddr => '192.168.1.2',         PeerPort => 45000,         Proto    => 'tcp' ); print $sock "Hello\n"; print <$sock>; close $sock;

After we create our TCP client socket using IO::Socket::INET, we immediately send our test string to the server using the print function. We use the diamond operator (<>) as the means to read from $sock and then anonymously pass this to the print function. Finally, the client socket is closed using the close function.

That's simple so far. Now, let's try the sysread and syswrite functions. The TCP server now looks like (strmtst2.pl):

use Socket; socket( srvSock, Socket::AF_INET, Socket::SOCK_STREAM, 0 ); $addr = inet_aton( '192.168.1.2' ); $paddr = sockaddr_in( 45000, $addr ); bind( srvSock, $paddr ); listen( srvSock, Socket::SO_MAXCONN ); while( true ) {     accept( cliSock, srvSock );     sysread( cliSock, $line, 128, 0 );     syswrite( cliSock, $line, length( $line ) );     close cliSock; }

After setting up the server socket, we enter the client accept loop. In this example, we use the sysread and syswrite functions to read from and write to the socket. The prototypes for the sysread and syswrite functions are:

 sysread handle, scalar, length, offset; syswrite handle, scalar, length;

Both functions take the socket to use for I/O and the scalar (string buffer, here $line). For sysread, we define the total length that we want to receive in the scalar argument and the offset into scalar we want the input data to be placed. For syswrite, we provide the scalar buffer and the length that we want to write.

Our client changes similarly (strmcli2.pl):

use IO::Socket::INET; $sock = IO::Socket::INET->new(         PeerAddr => '192.168.1.2',         PeerPort => 45000,         Proto    => 'tcp' ); $line = "Hello!\n"; syswrite( $sock, $line, length($line) ); sysread( $sock, $nline, 128, 0 ); print $nline, "\n"; close $sock;

After sending our single line with the syswrite function, we collect the response from the server with the sysread function, placing the read buffer into $nline.

Datagram Sockets

A variation of send is used exclusively by datagram sockets, while the recv function is used also (through the return of recv, which is the source address of the datagram). What differentiates these calls from our previously discussed stream calls is that these calls include addressing information. Because datagrams are not connected, we must define the destination address explicitly. Conversely, when receiving a datagram, the address information is also provided so that the source can be identified.

Let's look at a datagram server and client that provide the echo functionality illustrated previously by our stream socket examples. Our datagram server takes on a slightly different form. Additionally, we'll use the IO::Socket::INET module solely for both the server and the client (dgrmserv.pl).

# Server example use IO::Socket::INET; $sock = IO::Socket::INET->new(             LocalAddr => 'localhost',             LocalPort => 45000,             Proto     => 'udp',             ReuseAddr => 1 ); while (true) {     $from = recv( $sock, $line, 128, 0 );     send( $sock, $line, 0, $from ); } close $sock;

Using the object interface (IO::Socket::INET), we create a new SOCK_DGRAM socket (identified by protocol ‘udp') and automatically bind it to localhost and port 45000. Additionally, we specify the ReuseAddr socket option (SO_REUSEADDR) to enable immediate reuse of the local address. We then enter our infinite loop where we await a datagram and then bounce the datagram back to the source. Using the recv function (which can also be used on object interface sockets), we receive the datagram and store the payload into $line. We also store the result of recv into $from, which represents the source of the datagram. Next, we immediately send the datagram back to the source using the $from variable to direct the datagram in the send function.

In the client, we'll explore some of the object-oriented methods that are possible. Rather than call a function with the socket as the argument, we'll use the socket argument and invoke a method attached to it (dgramcli.pl).

# Client example use IO::Socket::INET; $sock = IO::Socket::INET->new(         PeerAddr => 'localhost',         PeerPort => 45000,         Proto    => 'udp' ); $line = "Hello!\n"; $sock->send( $line ); recv( $sock, $nline, 128, 0 ); print $line; close $sock;

We create the UDP socket with the new constructor, and this time use the PeerAddr and PeerPort to identify where this socket should be connected. Note that SOCK_DGRAM sockets (UDP) are disconnected by default; the only purpose for connection-based datagram sockets is so that destination address information need not be specified for each outgoing datagram. We construct a string that we'll send ($line) and then send this to the peer using the send function. Note the object-oriented usage of this call (object->method) and the fact that no destination was specified. This is because we specified the destination address when we created the socket. We expect a response from the server, so we use the standard recv call here to get the response and then emit it to standard-out using the print function. Finally, we close the socket using the close function.

Socket Options

Socket options permit an application to change some of the modifiable behaviors of sockets and the methods that manipulate them. For example, an application can modify the sizes of the send or receive socket buffers or the size of the maximum segment used by the TCP layer for a given socket.

Socket options are very simple in Perl. Options can be specified with the IO::Socket::INET with the new constructor, or with the standard setsockopt/getsockopt API. We'll look at examples of both.

Let's look at a simple example first. Let's say that we want to identify the size of the receive buffer for a given socket (option SO_RCVBUF). This can be done with the following code segment (sockopt1.pl):

use IO::Socket::INET; sock = IO::Socket::INET->new(             LocalAddr => 'localhost',             LocalPort => 5000,             Proto     => 'tcp' ); print $sock->getsockopt( Socket::SOL_SOCKET,                     Socket::SO_RCVBUF ); close $sock;

First, we create a new stream server socket (allow incoming client connections on any interface to port 23). Using the getsockopt call, we extract the receive buffer size for the socket. We specify the Socket::SOL_SOCKET argument because we're interested in a Sockets layer option (as compared to a TCP layer option). For the receiver buffer size, we specify Socket::SO_RCVBUF. The value returned from getsockopt is then emitted to standard-out using the print function.

Now, let's look at how an option is retrieved for a given socket, specifically, the linger option. Socket linger allows us to change the behavior of a stream socket when the socket is closed and data is remaining to be sent. After close is called, any data remaining will attempt to be sent for some amount of time. If after some duration, the data cannot be sent, then the data to be sent is abandoned. The time after the close to when the data is removed from the send queue is defined as the linger time. In Perl, we must deconstruct the structure that is provided by the host environment (sockopt2.pl).

use IO::Socket::INET; $sock = IO::Socket::INET->new( Proto => 'tcp' ); $ling = $sock->getsockopt( Socket::SOL_SOCKET, Socket::SO_LINGER ); ($ena, $val) = unpack( 'ii', $ling ); print $ena, "\n"; print $val, "\n"; close $sock;

The SO_LINGER option returns a binary packed structure that contains first an enable (1 for enable, 0 for disable) and then the time for linger in seconds. Using the unpack function, we unpack the binary structure into two independent 32-bit values. These are returned to $ena and $val, respectively. The default is 0 for both values, representing that the linger option is disabled. We could configure the linger option for enabled and 10 seconds as:

use IO::Socket::INET; $sock = IO::Socket::INET->new( Proto => 'tcp' ); my $linger = pack('ii', 1, 120); $sock->setsockopt( Socket::SOL_SOCKET, Socket::SO_LINGER, $linger ); close $sock;

The pack function takes the two arguments and packs them into two 32-bit binary values (as specified by the ‘ii' template).

Other Miscellaneous Functions

Let's now look at a few miscellaneous functions from the various Sockets APIs and the capabilities they provide. The DNS resolver permits us to resolve a host name to an IP address, or vice versa. Method gethostbyname provides name resolution given an FQDN; for example:

($name, $aliases, $addrtype, $length, @addrs) =     gethostbyname( "www.microsoft.com" );

where @addrs is a list of IP addresses in binary notation and $length refers to the number of addresses that were found. To emit the first IP address for the given domain in dotted-string notation, we could do:

print inet_ntoa( $addrs[0] ), "\n";

The other return variables are the official host name ($name), the official alias ($aliases), the address type (2 for Socket::AF_INET), the number of addresses found ($length), and finally the list of addresses (@addrs).

What if we want to go in the opposite direction, providing an IP address and get in return an FQDN? To achieve this, we use the gethostbyaddr:

$myaddr = inet_aton( "207.46.134.190" ); ($name, $aliases, $addrtype, $length, @addrs) =     gethostbyaddr( $myaddr, Socket::AF_INET ); print $name, "\n";

Now, let's consider the problem of identifying the port number for a given service. To retrieve the service information given a service name (such as ‘www'), the following can be done:

($name, $aliases, $port, $proto) = getservbyname( 'www', 'tcp' );

The values for this example include 'www' for $name, 'http' for $aliases, 80 for $port, and ‘tcp' for $proto. We can also retrieve the service by port number, such as:

($name, $aliases, $port, $proto) = getservbyport( 25, 'tcp' );

which would result in values 'smtp' for $name, 'mail' for $aliases, 25 for $port, and ‘tcp' for $proto.

Notification

As a final topic for Perl, let's look at the concept of event notification for sockets. This capability is commonly provided by the select function.

As we saw with C, the descriptors representing our IO channels are provided to the select method to identify when some event occurs. We can configure the select method to tell us when a channel is readable, writable, or if an error occurs on it. Further, we can also tell the select method to return after a configurable number of seconds if no event occurs. Consider the following Perl TCP server in Listing 12.1

Listing 12.1 Perl TCP server illustrating the select method.

start example
use Socket; socket( srvSock, Socket::AF_INET, Socket::SOCK_STREAM, 0 ); $addr = inet_aton( "192.168.1.2" ); $paddr = sockaddr_in( 45000, $addr ); setsockopt( srvSock, Socket::SOL_SOCKET, Socket::SO_REUSEADDR, 1 ); bind( srvSock, $paddr ); listen( srvSock, 1 ); while( 1 ) {   print "In the big loop\n";   accept( cliSock, srvSock );   $timeout = 5;   # Client loop   while( 1 ) {     $rin = '';     vec( $rin, fileno(cliSock), 1 ) = 1;     $nfound = select( $rout = $rin, undef, undef, $timeout );     if ($nfound) {       if ( vec($rout, fileno(cliSock), 1) == 1 ) {           # Don't mix select recv/send -- use sysread/syswrite instead           sysread( cliSock, $line, 128, 0 );           syswrite( cliSock, $line, length($line), 0 );       }     } else {     $to = "Timeout!\n";     syswrite( cliSock, $line, length($line), 0 );     }   } }
end example

This very simple server awaits a client connection and then upon receiving one will echo whatever it receives from the client. To determine when the client has sent something to be echoed, we use the select function. The select method works with file handles, so the fileno function must be used to convert the socket descriptor into a file number. We use the vec function to set the file handle in the read-set vector ($rin). In the select function, we can specify three vectors representing our request. The first vector indicates the file handles for which we want to be notified if a read event is generated (data is available on a given file handle for read). The second is a vector indicating write events, and the third is for error events. The last argument represents how much time to await an event before timing out. Note in this example, that we only specify read events and the timeout. For vectors that are not used, we pass in undef, which acts like a NULL vector (unspecified).

The return of select is the number of file handles that were set within vectors (in this case, the $rin vector). In this usage, the $rout is the test vector that we'll use to check to see what happened. As long as $nfound (number of bits set in the vectors) is non-zero, we'll check to see if our file-handles bit was set in $rout using the vec function. If it was set, we then use sysread to read from the socket and then loop the data back to the client using syswrite. If the timeout arrives before any event ($nfound is zero), we notify the peer of this event by writing 'Timeout!' to the client.



 < Day Day Up > 



BSD Sockets Programming from a Multi-Language Perspective
Network Programming for Microsoft Windows , Second Edition (Microsoft Programming Series)
ISBN: 1584502681
EAN: 2147483647
Year: 2003
Pages: 225
Authors: Jim Ohlund

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net