toadi has asked for the wisdom of the Perl Monks concerning the following question:

I tried several approaches, but I ran out of ideas how to do something :)
I have next piece of code:
#!/usr/bin/perl -w use IO::Socket; use Net::hostent; $PORT = 9000; $server = IO::Socket::INET->new( Proto => 'tcp', LocalPort => $PORT, Listen => SOMAXCONN, Reuse => 1); die "can't setup server" unless $server; print "[Server $0 accepting clients]\n"; while ($client = $server->accept()) { $client->autoflush(1); print $client "Welcome to $0.\n"; $hostinfo = gethostbyaddr($client->peeraddr); printf "[Connect from %s]\n", $hostinfo->name || $client->peerho +st; system('./sleep.pl'); close $client; }
Ok Ok, no use strict, but is just a small piece of example code.

See I have a client that connects to this server. Then it needs to run sleep.pl. But it's possible it can get another connect from a client while sleep.pl is still running. This code should wait until finished and the run again. As long as there are connects.
So each time there is a connect from the client it needs to start but there can be connects before sleep.pl ends, it should keep record of the connects and start sleep.pl as many times as it got a connection but one at a time.

Pfff, this was hard to explain...

I mucking arount with fork and wait but can't produce a good workable script :(

--
My opinions may have changed,
but not the fact that I am right

Edit: chipmunk 2001-12-11

Replies are listed 'Best First'.
Re: Wait for next
by MZSanford (Curate) on Dec 11, 2001 at 21:26 UTC
    I would imagine you want fork(), so you can process mutiple connections at once. Lincoln Stein's book "Network Programming With Perl" covers a few diffrent ways of doing this with, or without fork ... but i usually find fork the best. Here is some pseudo code (untested, but you get the idea):
    # setup $server as before while ($client = $server->accept()) { my $pid = fork(); if ($pid) { #parent my $hostinfo = gethostbyaddr($client->peeraddr); print "[$hostinfo being Handled by child with pid $pid]\n"; } else { #child print $client "Welcome to $0.\n"; system(qw/sleep.pl/); close($client); } }

    $ perl -e 'do() || ! do() ;' Undefined subroutine &main::try
Re: Wait for next
by Rhandom (Curate) on Dec 11, 2001 at 22:07 UTC
    If you only want to run them serially, then you might already have functioning code. The SOMAXCONN argument that you are giving to the listen parameter tells the kernel to accept up to than many connections (queues them), whether or not you have accepted on them. As soon as you accept, a spot in the listen queue is opened and somebody else can connect.

    However, under that senario, a client will connect and his connection will be open, but will not receive a greeting from the server until it is his turn.

    An alternate solution would be to use something like the Net::Server or Net::Daemon modules. These modules are intended for handling all of the server back end for you and you simply have to deal with handling the dialog with the client. To handle only having one sleep.pl run at a time, you could use file locking to assure that only one process gets it.

    For example:

    #!/usr/bin/perl package MyServer; use Net::Server::Fork; use Fcntl qw(LOCK_EX); @ISA = qw(Net::Server::Fork); MyServer->run(port => 20203); exit; sub process_request { my $self = shift; print STDOUT "Welcome to my server\r\n"; # while (<STDIN>){ # print "You said: $_"; # last if /quit/; # } print "Waiting to get lock on file\r\n"; my $lockfile = '/tmp/foo'; open(LOCK, $lockfile) || die "Couldn't open [$!]"; flock(LOCK,LOCK_EX) || die "Couldn't get lock [$!]"; print "Got lock, proceeding\r\n"; system('sleep.pl'); close(LOCK); print "All done, goodbye\r\n"; }

    There are many ways to do it. Just depends on what you need.

    my @a=qw(random brilliant braindead); print $a[rand(@a)];

Wait for it . . .
by Fletch (Bishop) on Dec 11, 2001 at 23:05 UTC