QuillMeantTen has asked for the wisdom of the Perl Monks concerning the following question:

Greetings,
after much trial and error I am almost done with the basic functionality of a messaging daemon summoner. Idea behind it is to make communication transparent (through filehandles) to other scripts and let the messaging daemon handle things (such as taking input from a network socket and putting output on an unix socket or in a named pipe)

I am now testing the following functionality :

I have one test script that forks, the father sending messages and the child on the receiving end.
Trouble is, the first message is sent and received correctly. The second message is received by the messenger daemon but never relayed to the child. I think the issue is somewhere in the following code :

sub relay{ my $self = shift; if(!ref($self)){ croak "can not call relay from a class"; } my $handle = $self->{input}->{fh}; given ($self->{input}->{type}){ when ('named_pipe'){ open $handle,'<',$self->{input}->{name}; while(<$handle>){ $self->_write($_); } } when('unix_socket'){ while(my $socket = $handle->accept()||croak "$!"){ while(<$socket>){ my $data = $_; print "I receive $data\n"; $self->_write($data); } } } when('network_socket'){ print "gonna try and listen on network socket named $self->{input}->{name}\n"; my $socket = $handle->accept()||croak"$!"; print "listening\n"; while(<$socket>){ my $data = $_; print "I receive $data\n"; $self->_write($data); } } } } sub _write{ my $self = shift; if(!ref $self){ croak "can not do that as a class!"; } my $input = shift; my @keys = keys $self->{output}; foreach my $key (@keys){ if(!defined($self->{output}->{$key}->{fh}) && !$self->{output} +->{$key}->{type} eq 'named_pipe'){ croak "undefined fh for key $key\n"; } given($self->{output}->{$key}->{type}){ when('named_pipe'){ open my $handle ,'>',$self->{output}->{$key}->{name} o +r croak "could not open output handle"; print $handle $input; close $handle; } when('unix_socket'){ my $server = $self->{output}->{$key}->{fh}; my $socket = $server->accept() or croak "$!"; print "trying to send $input to $self->{output}->{$key}->{name}"; print $socket $input or croak "$!"; } when('network_socket'){ my $server = $self->{output}->{$key}->{fh}; my $socket = $server->accept() or croak "$!"; print "tring to send $input to inet\n"; print $socket $input; print "done printing\n"; } } } }

specificaly in the "network_socket" cases.
After reading around I have found out that I very probably misunderstand the way one should use sockets, or named pipes for that matter. Here is an example of the kind of things I do to get hash structures transmitted (that's the code for the receiving end, the handle is for a named pipe)

open my $fh,'<',$request_file_name; my $params; eval{$params = fd_retrieve($fh)}; if($@){ print "continuing after error $@"; close $fh; redo; }

and now the testing code : here is the receiving process (listening to localhost:1066)

my $recsock; while(!defined $recsock){ eval{$recsock = IO::Socket::INET->new(PeerAddr=>'localhost',PeerPort=>1066,Pro +to=>'tcp')||croak"$!"}; } print "son here, opening inbound socket\n"; while(<$recsock>){ print "received $_"; }

and the writing process

my $c = 0; print"creating socket\n"; my $sock; while(!defined($sock)){ eval{$sock = IO::Socket::INET->new(PeerAddr=>'localhost',PeerPort=>1065,Proto=> +'tcp')or croak "$!"}; } while(1){ my $data = "trololol ".$c."\n"; print $sock $data or croak "$!"; $c++; }

You might notice that both of these processes, even the writing one connect to a peer and not the other way around.
I'm not sure if its a good idea but I felt more comfortable with having the messaging daemon summoner deal with things such as setting up the sockets, and to "keep it in the family" giving their handles to his little messenger daemons...

here is the code that creates both sockets :

$messenger_params{input}->{fh} = IO::Socket::INET->new( Listen=>$params->{input}->{Listen}, LocalAddr=>$params->{input}->{loca_addr}, Type=>SOCK_STREAM, Proto=>'tcp', Reuse=>1, LocalPort=>$params->{input}->{local_port}, )or croak "$!"; #and for the second one : $messenger_params{output}->{$key}->{fh} = IO::Socket::INET->new( LocalAddr=>$params->{output}->{$key}->{loc +al_addr}, LocalPort=>$params->{output}->{$key}->{loc +al_port}, Type=>SOCK_STREAM, Proto=>'tcp', Reuse=>1, Listen=>$params->{output}->{$key}->{listen +}, )or croak "$!";

I am eager to better my coding style too so if you have any suggestions toward making my code more readable/maintainable or at least less eye-gouging I will be most grateful.

Replies are listed 'Best First'.
Re: Inet socket to inet socket communication
by 1nickt (Canon) on Aug 26, 2015 at 18:35 UTC

    Hi QuillMeantTen, I am only addressing your last comment: if you have any suggestions toward making my code more readable/maintainable or at least less eye-gouging ... since you asked.

    I would make use of blank lines and spaces and quoted hash key names to improve readability. Of course there's a tradeoff in less code being viewable on a screen, but for me, it's faster to scroll (<CTRL-F>, <CTRL-B> ?) than to try to decipher overly compact source code. My eyes literally don't distinguish the point on the curly brace if it's butted up against a parenthesis. But I'm old. For example I would write:

    foreach my $key (@keys){ if(!defined($self->{output}->{$key}->{fh}) && !$self->{output} +->{$key}->{type} eq 'named_pipe'){ croak "undefined fh for key $key\n"; } given($self->{output}->{$key}->{type}){ when('named_pipe'){ open my $handle ,'>',$self->{output}->{$key}->{name} o +r croak "could not open output handle"; print $handle $input; close $handle; } # when ... } }
    as this:
    foreach my $key ( @keys ) { if ( ! defined ( $self->{'output'}->{$key}->{'fh'} ) && $self->{'output'}->{$key}->{'type'} ne 'named_pipe' ) { croak "undefined fh for key $key\n"; } given ( $self->{'output'}->{$key}->{'type'} ) { when ('named_pipe') { open my $handle, '>', $self->{'output'}->{$key}->{'name'} or croak "open failed: $!"; print $handle $input; close $handle or croak "close failed: $!"; } } }
    Alternatively sometimes readability trumps memory usage and I might make a copy of a variable if I was going to be using it a few times, and its current name was unwieldy, especially if that meant I could avoid splitting statements over two lines:
    foreach my $key ( @keys ) { my $foo = $self->{'output'}->{$key}; if ( ! defined $foo->{'fh'} and $foo->{'type'} ne 'named_pipe' ) { croak "undefined fh for key $key\n"; } given ( $foo->{'type'} ) { when ('named_pipe') { open my $handle, '>', $foo->{'name'} or croak "open failed: $! +"; print $handle $input; close $handle or croak "close failed: $!"; } } }
    There you go; this advice is definitely worth what it cost you :-)

    Update: removed a pair of artefactal parens

    The way forward always starts with a minimal test.
Re: Inet socket to inet socket communication
by QuillMeantTen (Friar) on Aug 27, 2015 at 07:45 UTC

    I Made it work!

    So why didnt it work the first time : because I kept opening and closing the output connection instead of keeping it open.
    Here is what I did :

    Since this code runs inside the read loop for each input it does not need to close and reopen sockets :D