in reply to stdin-socket without fork()??

You need to add STDIN and STDOUT to your $sel IO::Socket object and treat it like any other. If anything is available for reading, add it to the write queue for the other. If anything's in the write queue and the file handle is available for writing, write it.

Without selecting first (like you're doing implicitely via $sel->can_read), a sysread call will block until data is available to be read.

You may be interested in setting $|=1 (or doing $filehandle->autoflush), to keep stdio buffering from slowing you up.

Replies are listed 'Best First'.
RE: Re: stdin-socket without fork()??
by gharris (Beadle) on Nov 09, 2000 at 01:44 UTC
    That was how I wrote the first incarnation (I think at least).
    I am not polling for writable handles because in my previous experiences that was mostly unnecessary.
    The while loop exits immediately with nothing in @ready. That problem led me to believe that IO::Select was not happy with filehandles. At any rate, here is the complete script:
    use IO::Socket; use IO::Select; use IO::Handle; use strict; use warnings; my ($stdin, $stdout); my ($t_conn, $t_addr, $t_port, $t_buf); my ($buf, @ready, $socket, $sel, $ret); $t_addr = shift; $t_port = shift; $stdin = new IO::Handle; $stdin->fdopen(fileno(STDIN), 'r') $stdout = new IO::Handle; $stdout->fdopen(fileno(STDOUT), 'w') $t_conn = IO::Socket::INET->new(PeerAddr => $t_addr, PeerPort => $t_port, Proto => 'tcp'); if ( $t_conn->connected() ) { print 'connected'."\n"; } else { die 'could not establish a connection...'."\n"; } $t_conn->syswrite('Connected!'."\n"); $sel = new IO::Select(); $sel->add($t_conn); $sel->add($stdin); $stdout->syswrite('begin transmissions...'."\n"); print $sel->count()."\n"; while ( ( $sel->count() > 0 ) && ( @ready = $sel->can_read() ) ) { if ( length($buf) > 0 ) { $t_conn->syswrite($buf); } foreach $socket (@ready) { if ( $socket == $t_conn ) { if ( $t_conn->connected() ) { if ( $t_conn->sysread($buf, 1024) > 0 ) { $stdout->syswrite($buf); } else { print 'lost connection to tunnel, shutting down... +'."\n"; $sel->remove($t_conn); $t_conn->close(); $stdin->close(); $stdout->close(); } } else { print 'lost connection to tunnel, shutting down...'."\ +n"; $sel->remove($t_conn); $t_conn->close(); $stdin->close(); $stdout->close(); } } elsif ( $socket == $stdin ) { if ( $stdin->opened() ) { if ( $stdin->sysread($buf, 1024) > 0 ) { $t_conn->syswrite($buf); } else { print 'lost connection to host, shutting down...'. +"\n"; $sel->remove($t_conn); $t_conn->close(); $stdin->close(); $stdout->close(); } } else { print 'lost connection to host, shutting down...'."\n" +; $sel->remove($t_conn); $t_conn->close(); $stdin->close(); $stdout->close(); } } } $buf = ''; } print 'all connections closed... exiting...'."\n@ready\n".$sel->handle +s()."\n";
RE: Re: stdin-socket without fork()??
by gharris (Beadle) on Nov 09, 2000 at 21:26 UTC
    Well, I think I may have found my problem.
    I made a quick little script to test the basic select function call against STDIN:
    use strict; use warnings; my ($rin, $rout, $nfound); $rin = ''; vec($rin, fileno(STDIN), 1) = 1; $nfound = select($rout = $rin, undef, undef, 5); syswrite(STDOUT, "We stop here...\n");
    And I kept getting the same results, select returns immediately with nothing ready. So I decided that maybe it had something to do with the IO in the Windows NT console. So I copied that script over to my linux box (at home) and ran it there, and, well, it worked perfectly.
    Which means I wasn't going crazy (good thing), but that I might not be able to do what I want to do (bad thing).
    I did however write a very similar program in C that does work correctly, so I guess I will just have to write this in C.
    Thanks for your help, --Glenn