[Chapter 12] 12.5 IO Objects and Filehandles
Author: Sriram Srinivasan
Date: 1999-07-02T01:37:06Z

#

| Chapter 12 Networking with Sockets |

## 12.5 IO Objects and Filehandles

Perl supports the BSD `socket` call, which returns a filehandle, as `open` does for files and pipes. This filehandle can be used as an argument for all the built-in input-output operators: `<>` , `read`, `sysread`, `print`, `write`, `syswrite`, and so on. In addition, it can be used by socket-specific functions such as `send`, `recv`, and `setsockopt`.

The IO::Socket module's `new` method returns an object that can also be used as a parameter to these I/O routines. Internally, it calls `socket` and uses the typeglob corresponding to the filehandle to store other attributes; we described this hideous-looking trick in Section 8.1, "Efficient Attribute Storage". In other words, its return value is the same object that was given to `socket`, which is why it does not matter to the I/O operators which option you choose. My recommendation is to go for the considerably easier to use IO::Socket option.

IO::Select is another story, however. If performance is absolutely crucial, you may prefer to do yourself what IO::Select implements:

    $r_bitset = $w_bitset = $e_bitset = '';
    # Monitor $sock1 for reading
    vec($r_bitset, $sock1->fileno(), 1) = 1;
    # Monitor $sock2 for writing
    vec($w_bitset, $sock2->fileno(), 1) = 1;
    # Monitor both for errors
    $e_bitset = $r_bitset | $w_bitset;

    ($nfound, $timeleft) =
        select ($r_bitset, $w_bitset, $e_bitset, $timeout);

The native `select` function requires three bit vectors representing collections of open files, sockets, or pipes. Each bit in these bit sets corresponds to an integer file descriptor, which in turn is tracked by the appropriate filehandles or IO objects. The `fileno()` method of IO::Socket, or the built-in function, `fileno`, can be used to retrieve this number. The rest is simple: we create three bit sets, for checking readability, writability, and error conditions, and use `vec` to set the appropriate bits in each bit set. Before `select` returns, it modifies the bit sets to indicate which file descriptors are ready for doing input or output.

Because these bit sets are modified, we have to construct them all over again before going back to `select`, which gets to be somewhat expensive. Instead, a common technique is to make a copy of these sets before getting them clobbered by `select`:

    # Set up $r_bitset and $w_bitset once
    ...

    while (1) {
        ($nfound, $timeout) = select ($r_copy = $r_bitset,
                                      $w_copy = $w_bitset,
                                      $e_copy = $e_bitset, $timeout);

        # Check $r_copy, $w_copy for readiness ...
    }

Note that the assignment happens before `select` gets control, and `select` sees only `$r_copy`, `$w_copy`, and `$e_copy`, which it feels free to modify.

The only place where we really save time over using IO::Select is that we don't have to make a list of ready filehandles; we can process the bit set directly. For the applications I have built, this marginal gain in efficiency is not worth it, so I use IO::Select.

12.4 Real-World Servers |  | 12.6 Prebuilt Client Modules