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

Hi Monks,

Can someone please suggest how to queue up clients while server is busy with a particular operation, which doesnt use fork/threads.

for eg: server code is
#!/usr/bin/perl -w #tcpserver.pl use strict; use Data::Dumper; use IO::Socket::INET; # flush after every write $| = 1; my (@arr,@art,%hsh,$cin,$tims,$status,$data,%vrf,$x,$start); my ($socket,$client_socket,@client_reply,@client_verify,$client_reply) +; my @hash=({port=>'',tim=>''}); my ($peer_address,$peer_port); my $times_connect=0; # creating object interface of IO::Socket::INET modules which internal +ly does # socket creation, binding and listening at the specified port address +. $socket = new IO::Socket::INET ( #LocalHost => '127.0.0.1', LocalPort => '5000', Proto => 'tcp', Listen => 5, Reuse => 1 ) or die "ERROR in Socket Creation : $!\n"; my $timeData = scalar(localtime); print $timeData."\n"; print "SERVER Waiting for client connection on port 5000"; my $times_connected=0; $start=1; while(1) { # waiting for new client connection. $client_socket = $socket->accept(); # get the host and port number of newly connected client. $peer_address = $client_socket->peerhost(); $peer_port = $client_socket->peerport(); push @arr,$peer_port; $hsh{$peer_port}=1; if($start eq 1) # The very first client. { $status=1; # get your own MD5 } if($start >1) { $status=$client_reply; #It has to write its + own this time. } print "\nAccepted New Client Connection[$start] From : $peer_addre +ss, $peer_port\n at".scalar(localtime); # write operation on the newly accepted client. print $client_socket "$status\n"; $data = <$client_socket>; chomp($data); print "Received from Client :",$data; push @client_reply,$data; $client_reply.="$data {}"; print "\n\n LIST->$client_reply"; $start++; } $socket->close();


client
#!/usr/bin/perl #tcpclient.pl use strict; use IO::Socket::INET; use Digest::MD5 qw(md5 md5_hex md5_base64); # flush after every write $| = 1; my ($socket,$client_socket,$status,$data,@info,$file,$md_self,$x,$i,$a +1,@a1,@a2); # creating object interface of IO::Socket::INET modules which internal +ly creates # socket, binds and connects to the TCP server running on the specific + port. $socket = new IO::Socket::INET ( PeerHost => '127.0.0.1', PeerPort => '5000', Proto => 'tcp', ) or die "ERROR in Socket Creation : $!\n"; print "TCP Connection Success.\n"; # read the socket data sent by server. $data = <$socket>; # we can also read from socket through recv() in IO::Socket::INET # $socket->recv($data,1024); print "Received from Server : ",$data; chomp($data); if($data eq 1) { $file=createRandom(); $md_self= md5_hex($file); open(FL,'>disk1.txt'); print FL $file; close FL; open(FL,'disk1.txt'); $_=<FL>; close FL; if(md5_hex($_) eq $md_self) { $status="$file $md_self"; #send the file address and its M +D5: } sleep(20); } else { chomp($data); $x=0; @a1=split(" {}",$data); for $i(0..($#a1)) { @a2=(); @a2=split(' ',$a1[$i]); if(md5_hex($a2[0]) eq $a2[1]) { $x++; } } if ($x eq ($#a1+1)) { $file=createRandom(); $md_self= md5_hex($file); open(FL,'>disk1.txt'); print FL $file; close FL; open(FL,'disk1.txt'); $_=<FL>; close FL; if(md5_hex($_) eq $md_self) { $status=$file.' '.$md_self; #send the file address and its + MD5. } } else { $status="Could'nt verfiy"; } } # write on the socket to server. print $socket "$status\n" ; # we can also send the data through IO::Socket::INET module, # $socket->send($data); #sleep (10); $socket->close(); #### #To create random characters #### sub createRandom { my ($randChars, $number, $output, $new, $i); # create string in loop (each char is a loop iteration) for ($i = 0; $i < 5; $i++) { # get a random number for each digit $number = int(rand(36)); # convert to a number or a letter depending on value if ($number < 10) { # number -> ASCII number $output = $number + 48; } else { # letter -> ASCII letter $output = $number + 87; } # make the ASCII number a character and append to string $new = chr($output); $randChars = "$randChars$new"; } return ($randChars); }

while first client is done with its read/write/verify process, I want every client trying to connect with server to wait in a queue for a particular time window and be processed by server without exiting from the program.

I tried hitting by head hard to get a logic for this by using a table, but not quite sure how it is feasible. any help would be great. Thanks in advance.

Replies are listed 'Best First'.
Re: Timed client connection
by Corion (Patriarch) on Aug 10, 2010 at 11:41 UTC

    Why do you want to avoid fork/threads?

    You have two choices:

    1. Do the actual processing in an external child process, and tell every client to check back in 5 minutes to get their new status (wait again, or done)
    2. Implement nonblocking sockets and poll them, for example using Coro
Re: Timed client connection
by zentara (Cardinal) on Aug 10, 2010 at 14:34 UTC
    I hav'nt seen you use IO::Select yet. If you don't want to fork or thread the server's client connections, you could have a 2 step server, where the front end uses IO::Select to just accept connections and push the clients into a FIFO array. Then you could pop clients off of that array, and run there intense operations in separate threads or forks, by passing the client's socket filehandles off. If it all sounds too complicated for you, try something like POE, and look thru it's cookbook for server examples.

    Also see Simple threaded chat server and look at the server for "multiecho chat" and see how I stuff client sockets into a threads shared array.

    You need to think about this stuff for awhile before it makes sense. :-)


    I'm not really a human, but I play one on earth.
    Old Perl Programmer Haiku