Professional Web Applications Themes

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

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 ing up somewhere else: while ($client = $sock->accept() || $client = $sock->accept()) { # handle client here } I hope someone can help or provide an example. I've ...

  1. #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
    ing 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;
    }

    Craig Manley Guest

  2. #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())) {
    ....
    }

    Craig Manley Guest

  3. #3

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


    "Craig Manley" <glideraerobaticshotmail.com> wrote in message
    news:1113469375.529616.222890o13g2000cwo.googlegr oups.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


    Sisyphus Guest

  4. #4

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

    "Craig Manley" <glideraerobaticshotmail.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
    > ing 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

    --
    -------------------- [url]http://NewsReader.Com/[/url] --------------------
    Usenet Newsgroup Service $9.95/Month 30GB
    xhoster@gmail.com Guest

Similar Threads

  1. lsof - find both endpoints of a unix socket?
    By Frank Cusack in forum Linux / Unix Administration
    Replies: 1
    Last Post: December 2nd, 12:16 PM
  2. Replies: 1
    Last Post: September 3rd, 11:45 AM
  3. Send Message over UNIX Socket
    By Didatus in forum PERL Miscellaneous
    Replies: 2
    Last Post: August 20th, 11:00 AM
  4. UNIX Domain sockets on HPUX
    By Russ Jones in forum PERL Modules
    Replies: 1
    Last Post: June 27th, 12:59 PM

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139