in reply to Networking without a network

From my limited experience in simple network connections, the first problem you hit, is why isn't this bi-directional? why is it locked up?

See UNO perl examples for a great commented walkthru of basic socket code.

Here is a basic bidirectional socket connection.

#!/usr/bin/perl -w use strict; use IO::Socket; my ( $host, $port, $kidpid, $handle, $line ); #unless ( @ARGV == 2 ) { die "usage: $0 host port" } ( $host, $port ) = @ARGV || ('localhost',4242); # create a tcp connection to the specified host and port $handle = IO::Socket::INET->new( Proto => "tcp", PeerAddr => $host, PeerPort => $port ) or die "can't connect to port $port on $host: $!"; $handle->autoflush(1); # so output gets there right away print STDERR "[Connected to $host:$port]\n"; # split the program into two processes, idetical twins die "can't fork: $!" unless defined( $kidpid = fork() ); # the if{} block runs only in the parent process if ($kidpid) { # copy the socket to standard output while ( defined( $line = <$handle> ) ) { print STDOUT $line; } kill( "TERM", $kidpid ); # send SIGTERM to child } # the else{} block runs only in the child process else { # copy standard input to the socket while ( defined( $line = <STDIN> ) ) { print $handle $line; } }

I'm not really a human, but I play one on earth.
Old Perl Programmer Haiku

Replies are listed 'Best First'.
Re^2: Networking without a network
by Anonymous Monk on Feb 23, 2010 at 13:02 UTC
    Thank you zentara, a good link and a good example concerning socket programming. I'll save it for future reference.
    But I must have stated my problem badly. What I really want to do is running our app from the command line. Not through inetd, i.e. not by connecting to port 7000 (in this case).

    I can write a small perl script communicating to this application connecting to tcp port 7000 etc etc. But I am trying to do something different now.

    I may have misunderstood almost everything, but my approach was to hook inte the app's STDIN/STDOUT assuming those are the handles to hook. Let me illustrate with some code.

    #!/usr/local/bin/perl use strict; use warnings; use IPC::Open2; use IO::Handle; $/ = "\r"; my $CR = "\r"; my $NL = "\n"; my @msg = ('INIT', 'STATUS', 'QUIT' ); my ($reader, $writer) = (IO::Handle->new, IO::Handle->new); my @program_and_arguments = ('/usr/local/script/netdiag'); eval { open2($reader, $writer, @program_and_arguments); }; if ($@) { if ($@ =~ /^open2/) { warn "open2 failed: $!\n$@\n"; return; } die; } select $writer; $|++; select STDERR; $|++; select STDOUT; $|++; print STDERR "Here 1\n"; my $req = shift @msg; print $writer $req, $CR; print STDERR "Here 2\n"; # We come here, than it han +gs my $answer = <$reader>; die "1" unless $answer; print STDERR "SVR:$answer$NL"; [... keep up the dialog...] print STDOUT "Done$NL"; __END__
    /L
      There are a few programs around, that don't behave well with pipes, when they were meant to be run from a terminal. Maybe you have one there?

      Some commonly tried approaches are usually attempted. First try a sysread instead of <> on $reader, and use IO::Select to detect data in the pipeline.

      #pseudocode my $data while ($select->can_read){ if ( (my $length = sysread $reader, $data, 4096) > 0) { # do something with $data } }

      You might also want to test out a different IPC module, which may work better than IPC2. See I got IPC::Open3 to work! and Script hangs when called via IPC::Open3 and IPC3 buffer limit problem and Script hangs when called via IPC::Open3 for example.

      The IPC3 links above have code showing how to combine IO::Select with sysread....... that is your best first shot. The basic idea should work with IPC2 also. The last resort, if select and sysread fail, is to use a pty, like in Re: monitoring memory load.

      We really need to know what this program does. What does it expect on input, and what output does it deliver? Somehow, your data just sits in the pipeline buffer. You might also try the Expect module.


      I'm not really a human, but I play one on earth.
      Old Perl Programmer Haiku
      Your comment suggests that the program is waiting for /usr/local/script/netdiag to write something.

      Which may mean the "problem" (or rather, the fix) lies in said program - not in your small script.

      Considering this is a networking program - perhaps netdiag is expecting $CR$LF as line endings, not just $CR (why $CR there, not $LF?). It hasn't seen a full line yet, so it's not going to write anything.

      But I must have stated my problem badly.

      No.... I must have read your problem based only on the first paragraph.... sorry. my bad. But my other answer is good. :-) use sysread + select


      I'm not really a human, but I play one on earth.
      Old Perl Programmer Haiku