Need help with a simple UNIX sockets server based on IO::Socket::UNIX - Perl

This is a discussion on Need help with a simple UNIX sockets server based on IO::Socket::UNIX - Perl ; 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 } ...

+ Reply to Thread
Results 1 to 4 of 4

Need help with a simple UNIX sockets server based on IO::Socket::UNIX

  1. Default Need help with a simple UNIX sockets server based on IO::Socket::UNIX

    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:umper 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;
    }


  2. Default Re: Need help with a simple UNIX sockets server based on IO::Socket::UNIX

    Oops sorry, the working workaround (not solution) is this:
    while (($client = $sock->accept()) || ($client = $sock->accept())) {
    ....
    }


  3. Default Re: Need help with a simple UNIX sockets server based on IO::Socket::UNIX


    "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



  4. Default Re: Need help with a simple UNIX sockets server based on IO::Socket::UNIX

    "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

+ Reply to Thread

Similar Threads

  1. UNIX select() equivalent in Java for polling multiple sockets
    By Application Development in forum Java
    Replies: 1
    Last Post: 10-03-2007, 07:16 PM
  2. Threads, signals and sockets (on UNIX)
    By Application Development in forum Python
    Replies: 6
    Last Post: 06-11-2007, 12:35 PM
  3. Re: Threads, signals and sockets (on UNIX)
    By Application Development in forum Python
    Replies: 0
    Last Post: 06-11-2007, 07:09 AM
  4. Are Unix Domain sockets supported?
    By Application Development in forum Java
    Replies: 0
    Last Post: 03-29-2005, 04:35 PM
  5. UNIX Domain Sockets
    By Application Development in forum Perl
    Replies: 1
    Last Post: 08-18-2003, 11:51 AM