RE: :Socket::UNIX questions

From: Jim (jkipp5_at_comcast.net)
Date: 12/31/04


To: "'Dave Kettmann'" <dkettmann@netlogic.net>, "'Perl List \(E-mail\)'" <beginners@perl.org>
Date: Fri, 31 Dec 2004 10:55:12 -0500


 

>
> I am working with UNIX Sockets and have some questions that I
> cant seem to find answers to on the web.
>
> 1: Are UNIX sockets bi-directional?
>
> 2: If so, what is the proper way to 'setup' the connection?
> (will post what I have below)
>
> 3: Do UNIX sockets have less overhead than INET sockets?
>
> Here is what I have for the OO connections:
>
> Server:
>
> my $server = IO::Socket::UNIX->new(Local => "/tmp/mysock",
> Type => SOCK_DGRAM,
> Listen => 5 )
> or die $@;
>
> Client:
>
> my $client = IO::Socket::UNIX->new (
> Type => SOCK_DGRAM,
> Peer => "/tmp/mysock",
> )
> or die $@;
>
> Right now, I am able to send information from the client to
> the server, but not the other way around. When I try this, I
> get:send:
>
> Cannot determine peer address at server.pl line 21
>
> Here are lines 17-22:
>
> if($text ne 'exit')
> {
> print "\nReceived message '", $text,"'\n";
> my $send = "I got: $text\n";
> $server->send($send,128); # <------- Line 21
> }
>
> I have tried multiple things with the creation of the socket,
> but cant get the right combination. I am beginning to think
> that UNIX sockets are not bi-directional, but I hope someone
> proves me wrong.
>
> If more information is needed, let me know.
>
> Thanks for the help,
>
> Dave Kettmann
> NetLogic
> 636-561-0680
>

Hi Dave
I pasted some example code I have played with a while ago and it does work.
I can't rember which perldoc or perl book I got it from.

#### SERVER
use IO::Socket;
use POSIX ":sys_wait_h"; # (for WNOHANG)

# example using unix domain socks
# once the file is created as a socket, any client can
# interact with it

my $sockname = "/tmp/unixsockd.sock";

start_daemon();

sub start_daemon {
    my $pid;
    if ($pid = fork()) {
        # wait for child proc to die and do a non blocking wait for pending
zombies
        waitpid($pid, 0);
    } else {
        if ($pid = fork()) { exit; }
        $0 = "unixsockd: accepting connections on $sockname";
        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,
               ) or die "$0: error starting daemon on '$sockname': $@\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() ) {
        # fork yet another process to prevent buffer deadlock. one proc
writes to
        # the sock, the other reads the deamons response
        my $pid = fork(); die "Cannot fork\n" unless defined $pid;
        if ($pid) { # parent
            close $client; # no use to parent
            next; # be ready for another client
        }
        # child
        close $sock; # no use to child
        process_requests($client);
        exit; # terminate child
    }
}

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
        last if $line =~ /^\s$/; # 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;
}

## CLIENT

use IO::Socket;
my $sockname = "/tmp/unixsockd.sock";

my $client = IO::Socket::UNIX->new(
                 Peer => $sockname,
                 Type => SOCK_STREAM,
                 Timeout => 5,
             ) or die "$0: error connecting to '$sockname': $@\n";

my $pid = fork(); die "Cannot fork\n" unless defined $pid;

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);
    }
}

-- 
No virus found in this outgoing message.
Checked by AVG Anti-Virus.
Version: 7.0.296 / Virus Database: 265.6.7 - Release Date: 12/30/2004
 


Relevant Pages

  • Re: IO::Socket::UNIX questions
    ... Do UNIX sockets have less overhead than INET sockets? ... > or die $@; ... I am able to send information from the client to the ... > cant get the right combination. ...
    (perl.beginners)
  • IO::Socket::UNIX questions
    ... I am working with UNIX Sockets and have some questions that I cant seem to find answers to on the web. ... or die $@; ... Right now, I am able to send information from the client to the server, but not the other way around. ...
    (perl.beginners)
  • Re: UDP recvfrom unable to get senders address
    ... I have a udp local client server program and I am trying to print the ... By definition of UNIX sockets the other peer is always localhost. ... it makes no sense for a Unix socket client to bindat his end. ...
    (comp.unix.programmer)
  • Re: How to check UID of process on the other side of local TCP/UDP connection
    ... does doing a netstat and matching the client port with a pid work for you? ... Client communicates with server via TCP or UDP. ... Unix sockets (unless of course Unix sockets are the only good way to ...
    (Focus-Linux)