Are you really looking for a multithreaded daemon (i.e. one that uses Perl threads) or a multi-process daemon? Here's a (very simple) example that does what you describe with Net::Server::PreFork:
#!/usr/bin/perl
package MyEchoServer;
use strict;
use warnings;
use Net::Server::PreFork;
use base("Net::Server::PreFork");
my $self = bless { server => { port => [ 1025 ] },
logfile => "/tmp/clog",
},"MyEchoServer";
open(my $clog,">>",$self->{logfile}) or die "Can't open $self->{logfil
+e} : $!";
my %accept = ( ipconfig => "10.10.0.0",
set => sub { $self->{value}->{$_[0]}=$_[1] },
get => sub { print "$_[0] is set to $self->{valu
+e}->{$_[0]}\n" },
);
$self->run();
sub process_request {
my $self = shift;
print "> ";
while (<STDIN>) {
chomp;
my ($command,@param) = split;
if (exists($accept{$command})) {
print {$clog} "$command ".join(" ",@param)."\n"
or die "Can't print to $self->{logfile}";
if (ref($accept{$command}) eq "CODE") {
$accept{$command}->(@param);
} else {
print $accept{$command}."\n";
}
} else {
print "Don't know command $command\n";
}
print "> ";
}
}
This is the interaction with the server (using socat instead of netcat):
sh-2.05b$ socat readline tcp4:localhost:1025
> unknown
Don't know command unknown
> ipconfig
10.10.0.0
> set var1 one
> get var1
var1 is set to one
And this is the STDERR of the server and content of /tmp/clog:
2006/01/05-10:11:06 MyEchoServer (type Net::Server::PreFork) starting!
+ pid(23443)
Binding to TCP port 1025 on host *
Group Not Defined. Defaulting to EGID '104 111 104 29'
User Not Defined. Defaulting to EUID '1000'
2006/01/05-10:11:24 Server closing!
sh-2.05b$ cat /tmp/clog
ipconfig
set value one
get value
A couple of caveats with this code:
- Obviously this will only log commands the server recognizes.
- The processes do not share memory, this means that a value set in one connection (via the set command) will not exist in any of the other forked children. You need to implement some sort of shared memory to do that (either use threads with shared variables or use an IPC mechanism or a database etc.).
- All children inherit the log file handle and they'll all print to it but the output may be interleaved, you may want to look at a more robust logging mechanism (such as Log::Log4perl with Log::Log4perl::Appender::Synchronized).
Hope this helps.
A computer is a state machine. Threads are for people who can't program state machines. -- Alan Cox
|