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

I'm currently writing a preforking server, but I'm having problems deciding what value to give for the Listen parameter when opening the socket.

The behaviour I want is for incoming connections to be accepted until each child process is busy, but any connections after that should be rejected (i.e. no queueing).

So do I do this:

my $socket = IO::Socket::INET->new(LocalPort => 12345, Type => SOCK_STREAM, Reuse => 1, Listen => 1 );
or this:
my $socket = IO::Socket::INET->new(LocalPort => 12345, Type => SOCK_STREAM, Reuse => 1, Listen => MAX_SERVERS ); # MAX_SERVERS = total no. of child processes
I would guess at the second version, thinking that the socket is a single resource shared by the child processes. But what I don't want to happen is for each child to let MAX_SERVERS requests queue up - for this application some requests can take hours to complete, so it is better to just refuse connections when the server is busy.

Thanks in advance,

JJ

Replies are listed 'Best First'.
Re: Behaviour of 'Listen' parameter in socket for preforking server
by fokat (Deacon) on Sep 26, 2002 at 02:41 UTC
    You need to set the Listen value to either 1 or 0 depending on your OS. Note that this is not always supported. What will happen, is that one request will be queued until one process gets the chance to take it. This still has the inconvenient that you might have one connection stuck in listen state until one of the processes becomes ready again.

    I guess a better approach would be to have a single "dispatch" process that takes care of the children and the socket. The client would connect to this main socket and receive the address and port of a vacant server (or a new server would be fork()ed to handle this request, up to a maximum concurrent number of children/operations).

    This would be much more portable and reliable.

    Perhaps a bit more information about your problem and scenario could help us better help you :)

    Regards.

      More info...

      The OS is Tru64 UNIX, which runs an application to execute commands on Ericsson AXE10 telephone exchanges. This application can be run as an interactive shell, have a command file piped into it, or just run a single function expressed as an argument on the UNIX command line. Unfortunately it has a startup period of 15-20 seconds, during which time it uses a large amount of system resources, making it inefficient for entering single commands.

      What I am writing is a server that will prefork a number of child processes - each one will open a telnet session to localhost (using Net::Telnet) and start the command line app in interactive mode. Incoming connections will then be accepted and single commands forwarded to a free process, removing the startup delay as the application is already running.

      Most commands will execute fairly quickly, but some switch functions such as repair checks and backups can take more than an hour. If all of the forked processes are busy, I would like an incoming connection to be rejected (i.e. no queueing) as a queued connection could give the user the impression that their job is being processed when actually it is just waiting.

      The clients are mainly CGI scripts and cron jobs. They will all access the server through a Perl module - this module will generate the error message if it cannot open a socket. I can also then keep a log of failed connections.

      JJ

      Update:

      I have written some test code (on RedHat7.3 this time - just got home from work :-) and no matter what value I use for Listen, the server keeps accepting (and queueing) connections. I will try this on Tru64 UNIX tonight to see if it in an OS issue as fokat suggests.

      However on the bright side, the test code has proved that even if the server preforks a number of children, the queue is always shared between them (again, ++fokat for confirming this). So if there is one server processing a very time consuming request, incoming connections will not 'get stuck' behind it if other servers finish their jobs first (my original thought was that each child might have it's own queue).

      So how can the parent process tell how many children are idle (then new ones could be forked if this falls below a preset limit)?

      JJ