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

Hello, I have a big problem that I can't solve. I need to write something kinda telnet server in perl (not exactly telnet, but it should support 2-way communication with a child it started). I can't succeed redirecting input/output of a child to the internet socket - the child reports Bad file descriptor on every write to stdout). I've wrote a sample child in Perl to diagnose a problem (save to testfile-slave.pl):
#!/usr/bin/perl use strict; select(STDIN);$| = 1; select(STDOUT);$| = 1; print STDERR "starting interaction\n"; $! = ''; print "GET /\n\n"; print STDERR "printerr is $! " . fileno(STDIN) . ", " . fileno(STDOUT) + . "\n"; print STDERR "req sent\n"; $! = ''; while (<STDIN>) { my $v = $_; print STDERR "readerr is $!\n"; print STDERR $v; } print STDERR "readerr is $!\n"; print STDERR "done interaction\n"; ----------- I tried several versions of servers, and all behave the same: #------version1 - works fine on linux #!/usr/bin/perl use strict; use IO::Socket; my $conn = IO::Socket::INET->new( Proto => "tcp", PeerAddr => "192.168.0.12", #change to any hos +tname PeerPort => 80, ) || die("can't connect"); open(STDIN,"<&" . $conn->fileno); open(STDOUT,">&" . $conn->fileno); system("$^X testfile-slave.pl"); print STDERR "done\n"; -------------------- #---------version2 - windows-specific #!/usr/bin/perl #use strict; use IO::Socket; my $conn = IO::Socket::INET->new( Proto => "tcp", PeerAddr => "192.168.0.12", #use address of any web server here PeerPort => 80) || die("can't connect"); binmode($conn); open(STDIN,"<&" . $conn->fileno) || print STDERR "can't redir stdin\n" +; open(STDOUT,">&" . $conn->fileno) || print STDERR "can't redir stdout\ +n"; my $file = "testfile-slave.pl"; use Win32::Process; use Win32; my ($ProcessObj,$exitcode); if (Win32::Process::Create($ProcessObj, "$^X","$^X $file", 1, NORMAL_PRIORITY_CLASS,".")) { $ProcessObj->Wait(500000); $ProcessObj->Kill($exitcode); } else { print STDERR "failed executing $file\n"; }; print STDERR "done\n"; --------------------
It appears to be some problems with Windows (e.g. possibly total inability to redirect IO from sockets) - does anybody knows about this? May be using IPC::open3 and IO::Select will help? Tested on Win98SE with ActiveState perl 5.8.0. Thanks in advance. (PS: I've searched entire google, and didn't find anything useful).

BazB changed pre tags to code tags.

  • Comment on Redirecting input and output of child process to inet socket fails on Win32
  • Download Code

Replies are listed 'Best First'.
Re: Redirecting input and output of child process to inet socket fails on Win32
by crabbdean (Pilgrim) on Feb 29, 2004 at 14:20 UTC
    Only quickly reading over your problem, I once wrote a socket program on my Win2000 box. It worked fine. I then moved it over to a Win95 box and it didn't work at all. The problem may be the inability of the OS. Have you attempted to run this on a 2000 or NT box? I know that may not be a great help but its just my initial thoughts.

    Dean
Re: Redirecting input and output of child process to inet socket fails on Win32
by esskar (Deacon) on Feb 29, 2004 at 23:22 UTC
    I am a little bit confused. Maybe it's my english but don't you want to set up a server? Well, then you do not have to set PeerAddr and PeerPort but LocalAddr and LocalPort.
    my $listen = IO::Socket::INET->new( Listen => 5, LocalAddr => 'localhost', LocalPort => 8000, Proto => 'tcp') or die "listen: $!";
    HTH
    Update Forget the above... now i got it..
Re: Redirecting input and output of child process to inet socket fails on Win32
by fuzzycow (Sexton) on Mar 01, 2004 at 14:22 UTC
    You can try the Expect perl module (also available as ppm from ActiveState). Be ready for problems (both generic and windows-related), yet IMHO Expect is one of the more robust solutions for IPC. I would also recommend making your solution pure-perl, if possible, and not run external processes.