|
Packit |
7ef13a |
README for IO::Multiplex
|
|
Packit |
7ef13a |
|
|
Packit |
7ef13a |
IO::Multiplex is designed to take the effort out of managing
|
|
Packit |
7ef13a |
multiple file handles. It is essentially a really fancy front end to
|
|
Packit |
7ef13a |
the C<select> system call. In addition to maintaining the C<select>
|
|
Packit |
7ef13a |
loop, it buffers all input and output to/from the file handles. It
|
|
Packit |
7ef13a |
can also accept incoming connections on one or more listen sockets.
|
|
Packit |
7ef13a |
|
|
Packit |
7ef13a |
It is object oriented in design, and will notify you of significant events
|
|
Packit |
7ef13a |
by calling methods on an object that you supply. If you are not using
|
|
Packit |
7ef13a |
objects, you can simply supply __PACKAGE__ instead of an object reference.
|
|
Packit |
7ef13a |
|
|
Packit |
7ef13a |
You may have one callback object registered for each file handle, or
|
|
Packit |
7ef13a |
one global one. Possibly both -- the per-file handle callback object
|
|
Packit |
7ef13a |
will be used instead of the global one.
|
|
Packit |
7ef13a |
|
|
Packit |
7ef13a |
Each file handle may also have a timer associated with it. A callback
|
|
Packit |
7ef13a |
function is called when the timer expires.
|
|
Packit |
7ef13a |
|
|
Packit |
7ef13a |
Here's an example which implements the beginnings of a multiuser game:
|
|
Packit |
7ef13a |
|
|
Packit |
7ef13a |
use IO::Socket;
|
|
Packit |
7ef13a |
use IO::Multiplex;
|
|
Packit |
7ef13a |
use Tie::RefHash;
|
|
Packit |
7ef13a |
|
|
Packit |
7ef13a |
my $mux = new IO::Multiplex;
|
|
Packit |
7ef13a |
|
|
Packit |
7ef13a |
# Create a listening socket
|
|
Packit |
7ef13a |
my $sock = new IO::Socket::INET(Proto => 'tcp',
|
|
Packit |
7ef13a |
LocalPort => shift || 2300,
|
|
Packit |
7ef13a |
Listen => 4)
|
|
Packit |
7ef13a |
or die "socket: $@";
|
|
Packit |
7ef13a |
|
|
Packit |
7ef13a |
# We use the listen method instead of the add method.
|
|
Packit |
7ef13a |
$mux->listen($sock);
|
|
Packit |
7ef13a |
|
|
Packit |
7ef13a |
$mux->set_callback_object(__PACKAGE__);
|
|
Packit |
7ef13a |
$mux->loop;
|
|
Packit |
7ef13a |
|
|
Packit |
7ef13a |
# mux_connection is called when a new connection is accepted.
|
|
Packit |
7ef13a |
sub mux_connection {
|
|
Packit |
7ef13a |
my $package = shift;
|
|
Packit |
7ef13a |
my $mux = shift;
|
|
Packit |
7ef13a |
my $fh = shift;
|
|
Packit |
7ef13a |
|
|
Packit |
7ef13a |
# Construct a new player object
|
|
Packit |
7ef13a |
Player->new($mux, $fh);
|
|
Packit |
7ef13a |
}
|
|
Packit |
7ef13a |
|
|
Packit |
7ef13a |
package Player;
|
|
Packit |
7ef13a |
|
|
Packit |
7ef13a |
my %players = ();
|
|
Packit |
7ef13a |
|
|
Packit |
7ef13a |
sub new {
|
|
Packit |
7ef13a |
my $package = shift;
|
|
Packit |
7ef13a |
my $self = bless { mux => shift,
|
|
Packit |
7ef13a |
fh => shift } => $package;
|
|
Packit |
7ef13a |
|
|
Packit |
7ef13a |
# Register the new player object as the callback specifically for
|
|
Packit |
7ef13a |
# this file handle.
|
|
Packit |
7ef13a |
$mux->set_callback_object($self, $self->{fh});
|
|
Packit |
7ef13a |
print $self->{fh}
|
|
Packit |
7ef13a |
"Greetings, Professor. Would you like to play a game?\n";
|
|
Packit |
7ef13a |
|
|
Packit |
7ef13a |
# Register this player object in the main list of players
|
|
Packit |
7ef13a |
$players{$self} = $self;
|
|
Packit |
7ef13a |
$mux->set_timeout($self->{fh}, 1);
|
|
Packit |
7ef13a |
}
|
|
Packit |
7ef13a |
|
|
Packit |
7ef13a |
sub players { return values %players; }
|
|
Packit |
7ef13a |
|
|
Packit |
7ef13a |
sub mux_input {
|
|
Packit |
7ef13a |
my $self = shift;
|
|
Packit |
7ef13a |
shift; shift; # These two args are boring
|
|
Packit |
7ef13a |
my $input = shift; # Scalar reference to the input
|
|
Packit |
7ef13a |
|
|
Packit |
7ef13a |
# Process each line in the input, leaving partial lines
|
|
Packit |
7ef13a |
# in the input buffer
|
|
Packit |
7ef13a |
while ($$input =~ s/^(.*?\n)//) {
|
|
Packit |
7ef13a |
$self->process_command($1);
|
|
Packit |
7ef13a |
}
|
|
Packit |
7ef13a |
}
|
|
Packit |
7ef13a |
|
|
Packit |
7ef13a |
sub mux_close {
|
|
Packit |
7ef13a |
my $self = shift;
|
|
Packit |
7ef13a |
|
|
Packit |
7ef13a |
# Player disconnected;
|
|
Packit |
7ef13a |
# [Notify other players or something...]
|
|
Packit |
7ef13a |
delete $players{$self};
|
|
Packit |
7ef13a |
}
|
|
Packit |
7ef13a |
# This gets called every second to update player info, etc...
|
|
Packit |
7ef13a |
sub mux_timeout {
|
|
Packit |
7ef13a |
my $self = shift;
|
|
Packit |
7ef13a |
my $mux = shift;
|
|
Packit |
7ef13a |
|
|
Packit |
7ef13a |
$self->heartbeat;
|
|
Packit |
7ef13a |
$mux->set_timeout($self->{fh}, 1);
|
|
Packit |
7ef13a |
}
|