package MyPlexer; use base qw(Net::Server::Multiplex); sub mux_input { #...code... } __PACKAGE__->run();
This takes some nice features of Net::Server (like the server listen socket setup, configuration file processing, safe signal handling, convenient inet style STDIN/STDOUT handling, logging features, deamonization and pid tracking, and restartability -SIGHUP) and some nice features of IO::Multiplex (automatic buffered IO and per-file-handle objects) and combines them for an easy-to-use interace.
See examples/samplechat.pl distributed with Net::Server for a simple chat server that uses several of these features.
$self->configure_hook; $self->configure(@_); $self->post_configure; $self->post_configure_hook; $self->pre_bind; $self->bind; if (Restarting server) { $self->restart_open_hook(); } $self->post_bind_hook; $self->post_bind; $self->pre_loop_hook; $self->loop; # This basically just runs IO::Multiplex::loop # For routines inside a $self->loop # See CLIENT PROCESSING below $self->pre_server_close_hook; $self->post_child_cleanup_hook; $self->server_close; if (Restarting server) { $self->restart_close_hook(); $self->hup_server; # Redo process again starting with configure_hook }
$self->{server}->{client} = Net::Server::Proto::TCP->accept(); # NOTE: Multiplexed with mux_input() below if (check_for_dequeue seconds have passed) { $self->run_dequeue(); } $self->get_client_info; $self->post_accept_hook; # Net::Server style if ($self->allow_deny && $self->allow_deny_hook) { # (Net::Server style $self->process_request() is never called.) # A unique client specific object is created # for all mux_* methods from this point on. $self = __PACKAGE__->new($self, client); $self->mux_connection; # IO::Multiplex style for (every packet received) { $self->mux_input; # NOTE: Multiplexed with accept() above } } else { $self->request_denied_hook; # Notice that if either allow_deny or allow_deny_hook fails, then # new(), mux_connection(), and mux_input() will never be called. # mux_eof() and mux_close() will still be called, but using a # common listen socket callback object instead of a unique client # specific object. } $self->mux_eof; $self->post_process_request_hook; $self->mux_close;
This process then loops multiplexing between the accept() for the next connection and mux_input() when input arrives to avoid blocking either one.
The loop() method of Net::Server has been overridden to run the loop routine of IO::Multiplex instead. The Net::Server methods may access the IO::Multiplex object at "$self->{mux}" if desired. The IO::Multiplex methods may access the Net::Server object at "$self->{net_server}" if desired.
The process_request() method is never used with this personality.
The other Net::Server hooks and methods should work the same.
$self->{net_server}->{mux}->set_timeout($fh, $seconds_from_now);
$fh may be either a client socket or a listen socket file descriptor within the mux. $seconds_from_now may be fractional to achieve more precise timeouts. This is used in conjunction with mux_timeout, which you should define yourself.
Example: $self->{peerport} = $self->{net_server}->{server}->{peerport};
If you need to use the IO::Multiplex style set_timeout / mux_timeout interface, you cannot use the Net::Server style check_for_dequeue / run_dequeue interface. It will not work if the check_for_dequeue option is specified. The run_dequeue method is just a compatibility interface to comply with the Net::Server::Fork style run_dequeue but is implemented in terms of the IO::Multiplex style set_timeout and mux_timeout methods.
This package may be distributed under the terms of either the GNU General Public License or the Perl Artistic License All rights reserved.
IO::Multiplex by Bruce Keeler <bruce@gridpoint.com>.