Hi. I've tried to create a simple client + server that communicate through a unix socket. As with all socket servers, it has a loop where it waits for connections: while ($client = $sock->accept()) { # handle client here } The problem is that $sock->accept() is returning undef on each alternate client connection with error "No child processes". I made this temporary workaround that does work but of course I must be screwing up somewhere else: while ($client = $sock->accept() || $client = $sock->accept()) { # handle client here } I hope someone can help or provide an example. I've included the client + server code below for those who are interrested in taking a peek. Thanks, Craig Manley ############ client ############ #!/usr/bin/perl -w use strict; use IO::Socket; my $sockname = 'mysocket'; my $client = IO::Socket::UNIX->new('Peer' => $sockname, 'Type' => SOCK_STREAM, 'Timeout' => 50) or die "$0: error connecting to '$sockname': $ [at] \n"; my $pid = fork(); unless(defined($pid)) { die("Fork this! I cannot forking fork!\n"); } if ($pid) { write_sock(); waitpid($pid, 0); } else { read_sock(); } sub write_sock { for (1..10) { print $client "testline number $_\n"; # print to socket } print $client "\n"; # empty line causes server to terminate connection print "Done writing.\n"; # (goes to stdout, not socket) } sub read_sock { while (my $line = <$client>) { print $line; # report to stdout # simulate someone reading slooowly (50ms/line): select(undef, undef, undef, 0.05); } } ########### server ############ #!/usr/bin/perl -w use strict; use IO::Socket; use POSIX ":sys_wait_h"; # (for WNOHANG) use Data::Dumper qw(Dumper); # example using unix domain socks # once the file is created as a socket, any client can # interact with it my $sockname = 'mysocket'; service_clients( get_sock() ); # wait for incoming requests sub get_sock { unlink $sockname; my $sock = IO::Socket::UNIX->new('Local' => $sockname, 'Type' => SOCK_STREAM, 'Listen' => SOMAXCONN) || die "$0: error starting daemon on '$sockname': $ [at] \n"; # you might want to change permissions and ownership, e.g.: #chmod 0600, $sockname; #chown scalar getpwnam('nobody'), 0, $sockname; return $sock; } sub service_clients { my $sock = shift; $SIG{CHLD} = \&reaper; my $client; while ($client = $sock->accept()) { # Why the hell does it return undef on the next iteration? # while ($client = $sock->accept() || $client = $sock->accept()) { # This strangely enough does work. # fork yet another process to prevent buffer deadlock. one proc writes to # the sock, the other reads the deamons response my $pid = fork(); unless(defined($pid)) { die("Fork this! I cannot forking fork!\n"); } if ($pid) { # parent print "$pid $$: I'm the parent and am going to wait for another client.\n"; close($client); # no use to parent next; # be ready for another client } print "$pid $$: I'm the child and I'm going to service the client.\n"; # child close($sock); # no use to child process_requests($client); print "$pid $$: I'm the child and I'm going to exit.\n"; exit; # terminate child } print "Damnit! I'm the server and I finished unexpectedly: $!\n"; } sub process_requests { my $client = shift; $0 = "unixsockd: handling requests..."; # read from client until empty line which causes it to close connection while ( my $line = <$client> ) { # read line from socket if ($line =~ /^\s$/) { last; # exit on empty line } chomp($line); # put some more useful code here to read each line or whatever... printf $client "%s: %s, handled by PID %d\n", scalar localtime(time), $line, $$; # return something to client } } sub reaper { while (waitpid(-1,WNOHANG) > 0) {} $SIG{CHLD} = \&reaper; }
Oops sorry, the working workaround (not solution) is this: while (($client = $sock->accept()) || ($client = $sock->accept())) { .... }
"Craig Manley" <glideraerobatics@hotmail.com> wrote in message news:1113469375.529616.222890@o13g2000cwo.googlegroups.com... > Hi. I've tried to create a simple client + server that communicate > through a unix socket. > What you have provided doesn't look all that simple to me. At its simplest a server script (which listens eternally, but can accept only one connection at a time) could look like this: ------------------------------------------- use strict; use IO::Socket; my ($client, $data_read); # Server listens at port 2009, for example. my $server = IO::Socket::INET->new(LocalPort => 2009, Type => SOCK_STREAM, Reuse => 1, Listen => 1 ) or die "Couldn't be a tcp server on port 2009: $!\n"; while(1) { print "Server waiting\n"; $client = $server->accept(); $data_read = <$client>; # Expects a single line # Do something with the message received from client - # in this case echo the message back. print $client $data_read; close($client); } __END__ ---------------------------------- and an (also eternal) client script could look like this: ------------------------------------ use strict; use warnings; use IO::Socket; my $remote; my $port = 2009; # port at which server listens my $host = '192.168.0.2'; # server's address while(1) { $remote = IO::Socket::INET->new( Proto => "tcp", PeerAddr => $host, Type => SOCK_STREAM, PeerPort => $port); unless ($remote) { die "cannot connect to http daemon on $host\n$!\n"; } # This particular script sits here, waiting for input .... my $data_to_send = <STDIN>; print $remote "$data_to_send\n" or die "Unable to send: $!\n"; # Cater for a multiline reply from the server my $data_received = ''; while(<$remote>) {$data_received .= $_} # Do something with the reply - # in his case simply print out the reply print $data_received, "\n"; close($remote); } __END__ --------------------------------------------- That's taken from actual scripts that I use on linux, but they have been modified - which means that I could have rendered them unusable (through some stupid error). You'll note that there's no use of IO::Socket::UNIX. Do you need to use that module ? If so, and you strike difficulty modfiying the above script(s), then let us know. There's also no forking. Do you need to fork ? Even if you do, you'll probably find it useful to get your script working under a scenario where forking is not required, and then develop it to incorporate forking. Hth. Cheers, Rob
"Craig Manley" <glideraerobatics@hotmail.com> wrote: > Hi. I've tried to create a simple client + server that communicate > through a unix socket. > > As with all socket servers, it has a loop where it waits for > connections: > > while ($client = $sock->accept()) { > # handle client here > } > > The problem is that $sock->accept() is returning undef on each > alternate client connection with error "No child processes". This is just a wild guess, but I think that what is happening is that your $sock->accept call is being interupted by the SIGCHLD, and is not getting automatically restarted once the sig handler finishes. > > I made this temporary workaround that does work but of course I must be > screwing up somewhere else: > > while ($client = $sock->accept() || $client = $sock->accept()) { > # handle client here > } Since it appears that you want the loop to be infinite, why not just make it explicitly infinite? while (1) { my $client=$sock->accept(); unless (defined $client) { next if $! eq 'Whatever that error was'; die "Unexpected error $!"; } #..... } > I hope someone can help or provide an example. I've included the client > + server code below for those who are interrested in taking a peek. Looking through some old code I have, I see that I don't use a sig handler at all. I just put the "while (waitpid(-1,WNOHANG) > 0) {}" directly into "accept" loop, as the first command after the accept. I don't recall exactly why I did that, but it may have been due to a problem like what you see. In this method, old forked servers stick around as zombies slightly longer (until the next client connects), but I don't think that that is a big deal. > > Thanks, > Craig Manley Xho -- -------------------- http://NewsReader.Com/ -------------------- Usenet Newsgroup Service $9.95/Month 30GB