|
Posted by Craig Manley on April 14, 2005, 3:02 am
Please log in for more thread options
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 = &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 %dn",
scalar localtime(time), $line, $$;
# return something to client
}
}
sub reaper {
while (waitpid(-1,WNOHANG) > 0) {}
$SIG = &reaper;
}
|
|
Posted by Craig Manley on April 14, 2005, 3:22 am
Please log in for more thread options
Oops sorry, the working workaround (not solution) is this:
while (($client = $sock->accept()) || ($client = $sock->accept())) {
....
}
|
|
Posted by Sisyphus on April 17, 2005, 10:52 pm
Please log in for more thread options
> 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 waitingn";
$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 $hostn$!n";
}
# This particular script sits here, waiting for input ....
my $data_to_send = <STDIN>;
print $remote "$data_to_sendn"
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
|
|
Posted by xhoster on April 18, 2005, 7:24 pm
Please log in for more thread options
> 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
|
| Similar Threads | Posted | | DBD:Excel on unix machine | March 9, 2006, 11:18 am |
| OLE Automation using Perl on a Unix box? | April 18, 2006, 7:27 pm |
| Passing a DBI connection between [Unix] processes | January 7, 2005, 1:01 pm |
| Windows Registry manipulation using Unix | April 29, 2005, 11:46 am |
| uncompressing unix Z files on Win32 | November 16, 2005, 8:29 pm |
| unix perl module install errors | November 11, 2004, 3:36 pm |
| Namespace for Unix File Permission checker | August 6, 2005, 9:17 pm |
| Required Perl Developer w/ UNIX. SQL and Shell Scripting. | March 24, 2006, 6:41 pm |
| creating perl binary using PAR module , execution error under unix | March 15, 2008, 7:06 am |
| Help with Net::SFTP when sftp on unix works. | September 21, 2004, 11:14 am |
|