The IO::Select Module


 
Network Programming with Perl
By Lincoln  D.  Stein
Slots : 1
Table of Contents
Chapter  12.   Multiplexed Applications

    Content

Perl versions 5.003 and higher come with an object-oriented wrapper class called IO::Select. You create an IO::Select object, add to it the handles you wish to monitor, and then call its can_read() , can_write() , or has_exceptions() methods to wait for one or more of the object's handles to become ready for I/O.

$select = IO::Select->new([@handles])

The IO::Select new() class method creates a new IO::Select object. It can be called with a list of handles, in which case they will be added to the set that IO::Select monitors , or it can be called with an empty argument list, in which case the monitor set will be initially empty.

The handle list can be composed of any type of filehandle including IO::Handle objects, globs , and glob references. You may also add and remove handles after the object is created.

$select->add(@handles)

This adds the list of handles to the monitored set and returns the number of unique handles successfully added. If you try to add the same filehandle multiple times, the redundant entries are ignored.

$select->remove(@handles)

This removes the list of filehandles from the monitored set. IO::Select indexes its handles by file number, so you can refer to the handle one way when you add it (e.g., STDOUT ) and another way when you remove it (e.g., \*STDOUT ).

$value = $select->exists($handle)

$count = $select->count

These are utility routines. The exists() method returns a true value if the handle is currently a member of the monitored set. The count() method returns the number of handles contained in the IO::Select set.

The can_read() , can_write() , and has_exceptions() methods monitor the handle list for changes in status.

@readable = $select->can_read([$timeout])

@writable = $select->can_write([$timeout])

@exceptional = $select->has_exception([$timeout])

The can_read() , can_write() , and has_exception() methods each call select() on your behalf , returning an array of filehandles that are ready for reading or writing or have exceptional conditions pending. The call blocks until one of the handles in the IO::Select object becomes ready, or until the optional timeout given by $timeout is reached. In the latter case, the call returns an empty list. The timeout is expressed in seconds, and can be fractional .

Any of these methods can return an empty list if the process is interrupted by a signal. Therefore, always check the returned list for filehandles, even if you have provided no timeout.

If you wish to select for readers and writers simultaneously , use the select() method.

($rout,$wout,$eout) = IO::Select->select($readers, $writers, $except [,$timeout])

select() is a class method that waits on multiple IO::Select sets simultaneously. $readers, $writers , and $except are IO::Select objects or undef , and $timeout is an optional time-out period in seconds. When any handle in any of the sets becomes ready for I/O, select() returns a three-element list, each element an array reference containing the handles that are ready for reading or writing, or that have exceptional conditions. If select() times out or is interrupted by a signal before any handles become ready, the method returns an empty list.

Exceptional conditions on sockets are not what this term may imply. An exceptional condition occurs when a TCP socket receives urgent data (we talk about how to generate and handle urgent data in Chapter 17). An I/O error on a socket does not generate an exceptional condition, but instead makes the socket both readable and writable. The nature of the error can then be detected by performing a read or write on the socket and checking the $! variable.

IO::Select->select() can be used to put the current process to sleep for a fractional period of seconds. Simply call the method using undef for all three IO::Select sets and the number of seconds you wish to sleep. This code fragment causes the program to pause for 0.25 seconds:

 @dis3:IO::Select->select(undef,undef,undef,0.25); 

As with sleep() , select() returns prematurely if it is interrupted by a signal. Also don't count on getting a pause of exactly 250 milliseconds , because select() is limited by the underlying resolution of the system clock, which might not provide millisecond resolution. To get a version of sleep that has microsecond resolution, use the Time::HiRes module, available from CPAN.

The Built-in select() Function

The built-in select() function is the Perl primitive that IO::Select uses internally. It is called with four arguments, like this:

 $nready = select($readers,$writers,$exceptions,$timeout); 

Sadly, select() 's argument-passing scheme is archaic and unPerlish, in volving complex manipulation of bit vectors. You may see it in older scripts, but IO::Select is both easier to use and less prone to error. However, you might want to use select() to achieve a fractional sleep without importing IO::Select:

 select(undef,undef,undef,0.25); 

Don't confuse the four-argument version of select() with the one-argument version discussed in Chapter 1. The latter is used to select the default filehandle used with print() .

The perlfunc manual pages give full details on the built-in select() function.

When Is a Filehandle Ready for I/O?

To use select() to its best advantage, it's important to understand the rules for a handle's readiness for I/O. Some of the rules apply equally to ordinary filehandles, pipes, and sockets; others are specific to sockets. Filehandles, pipes, and sockets are all ready for reading when:

  1. The filehandle has pending data . If there is at least 1 byte of data in the file-handle's input buffer (the receive buffer in the case of sockets), then select() indicates that the filehandle is ready for reading. sysread () on the filehandle will not block and returns the number of bytes read.

For sockets, this rule can be modified by setting the value of the receive buffer's "low water mark" as described in the next section.

  1. There is an end of file on the filehandle . select() indicates that a filehandle is ready for reading if the next read returns an end of file. The next call to sysread() will return numeric 0 without blocking. This occurs in normal filehandles when the end of the file is reached, and in TCP sockets when the remote host closes the connection.

  2. There is a pending error on the filehandle . Any I/O error on the filehandle also causes select() to indicate that it is ready for reading. sysread() returns undef and sets $! to the error code.

In addition, select() indicates that a socket is ready for reading when:

  1. There is an incoming connection on a listen socket . select() indicates that a listen socket is ready for reading if there is a pending incoming connection. accept() returns the connected socket without blocking.

  2. There is an incoming datagram on a UDP socket . A socket is ready for reading if it uses the UDP protocol and there is an incoming datagram waiting to be read. The recv() function returns the datagram without blocking. We discuss UDP in Chapter 18.

Filehandles, pipes, and sockets are all ready for writing when:

  1. There is room in the output buffer for new data . If there is at least 1 byte of free space in the filehandle's output buffer (the send buffer in the case of sockets), then syswrite() of a single byte will succeed without blocking. Calling syswrite() with more than 1 byte may still block, however, if the amount of data to write exceeds the amount of free space. On sockets, this behavior can be adjusted by setting the send buffer's low water mark.

If the filehandle is marked as nonblocking, then syswrite() always succeeds without blocking and returns the number of bytes actually written. We discuss nonblocking I/O in Chapter 13.

  1. There is a pending error on the filehandle . If there is an I/O error on the filehandle, then select() indicates that it is ready for writing. syswrite() will not block, but returns undef as its function result. $! contains the error code.

In addition, sockets are ready for writing when:

  1. The peer has closed its side of the connection . If the socket is connected and the remote end has closed or shutdown() its end of the connection, then select() indicates that the socket is ready for writing. The next syswrite() attempt will generate a PIPE exception. If you ignore or handle PIPE signals, then syswrite() returns undef and $! is equal to EPIPE . Local pipes also behave in this way.

  2. A nonblocking connect has been initiated, and the attempt completes . When a TCP socket is nonblocking and you attempt to connect it, the call to connect() returns immediately and the connection attempt continues in the background. When the connect attempt eventually completes (either successfully or with an error), select() indicates that the socket is ready for writing. This is discussed in more detail in Chapter 13.

Exceptional conditions apply only to sockets. There is only one common exception, which occurs when a connected TCP socket has urgent data to be read. We discuss how urgent data works in Chapter 17.

Combining select() with Standard I/O

When using select() to multiplex I/O, you must be extremely careful not to mix it with functions that use stdio buffering. The reason is that the stdio library maintains its own I/O buffers independent of the buffers used by the operating system. select() doesn't know about these buffers; as a result it may indicate that there's no more data to be read from a filehandle, when in fact there is data remaining in the buffer. This will lead to confusion and frustration.

In multiplexed programs you should avoid the <> operator, print() , and read() , as well as the built-in getline() function and the IO::Handle->getline() method. Instead, you should use the low-level sysread() and syswrite() calls exclusively. This makes it difficult to do line-oriented I/O. However, Chapter 13 develops some modules that overcome this limitation.

Adjusting the Low Water Marks

On some versions of UNIX, you can adjust when a socket is ready for reading or writing by changing the low water marks on the socket's send and/or receive buffers. The receive buffer's low water mark indicates the amount of data that must be available before select() will indicate that it is ready for reading and sysread() can be called without blocking. The low water mark is 1 byte by default, but you can change this by calling setsockopt() with the SO_RECVLOWAT option. You might want to adjust this if you are expecting transmissions of a fixed size from the peer and don't want to bother processing partial messages.

When writing to a socket, the low water mark indicates how many bytes of data can be written to the socket with syswrite() without blocking. The default is 1 byte, but it can be changed by calling setsockopt() with the SO_SNDLOWAT option.

Changing a socket's low water marks is nonportable. It works on most versions of UNIX but fails on Windows and Macintosh machines. In addition, the Linux kernel (up through version 2.4) allows the receive buffer's low water mark to be set, but not the send buffer's.


   
Top


Network Programming with Perl
Network Programming with Perl
ISBN: 0201615711
EAN: 2147483647
Year: 2000
Pages: 173

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