in reply to Re: IO::Socket tutorial
in thread IO::Socket tutorial

Thanks -- I'll look at POE. As for example client code, it is just unbelievably {and unfixably} dumb:
sub command { my $cmd = "$_[0]\r\n" ; print $server $cmd ; my $resp = <$server> ; return undef if $resp !~ /^[123]/ ; return $resp ; }
I don't even remember what got me thinking that IO::Socket's can be used as file descriptors {I just looked and can't find it in the man pages..sigh} I guess what I can do is do a 'send' with the $cmd my sub is given and then I need to replace the <$server> with something that'll timeout and then I can close/reopen the socket and try again. POE seems fancier than I need for this {although I see that it can handle the event loop of Tk, something I had trouble getting to work correctly}

Replies are listed 'Best First'.
Re^3: IO::Socket tutorial
by haukex (Bishop) on Feb 19, 2020 at 15:48 UTC
    I don't even remember what got me thinking that IO::Socket's can be used as file descriptors

    Technically they can be used like handles (not descriptors), they're subclasses of IO::Handle. But as you discovered, doing a readline on them is blocking; from my experience I very much prefer non-blocking operations, and those are IMHO best abstracted via an event-based interface.

    In terms of example code, I should have been more specific: a Short, Self-Contained, Correct Example.

      I seem to have replied but forgot to post it... duh. Anyhow, I'm thinking of sticking with IO::Select and it looks very easy. I create a new Select object initialized to my TCP connection, then I can do a can_read with a timeout, and if it doesn't time out I can use ->getlines to suck up what was sent. If that's all that I was expecting {the returned stuff is terminated by a line with just a ".", as with RCS and unix-mail} I'm done, otherwise I go back and can_read again. Either I get all I needed or a can_read returns a timeout. Seems pretty easy... I can handle the recovery code when it times out. THANKS!!
        I'm thinking of sticking with IO::Select and it looks very easy. ... then I can do a can_read with a timeout, and if it doesn't time out I can use ->getlines to suck up what was sent

        No, unfortunately it's not that easy. The reason is that can_read will fire even if there's only a single byte waiting to be read, and readline and friends will still hang because it's looking for a full line, which the server might not have sent.

        srv.pl:

        use warnings; use strict; use IO::Select; use IO::Socket; my $sock = IO::Socket::INET->new( Listen=>1, ReusePort=>1, LocalAddr=>'127.0.0.1', LocalPort=>1235 ) or die "sock: $@"; my $sel = IO::Select->new($sock); while ( my @ready = $sel->can_read ) { for my $fh (@ready) { if ($fh == $sock) { my $cli = $sock->accept; print "New client\n"; $sel->add($cli); syswrite $cli, "x"; } } }

        cli.pl:

        use warnings; use strict; use Data::Dumper; use IO::Select; use IO::Socket; my $sock = IO::Socket::INET->new( PeerAddr=>'127.0.0.1', PeerPort=>1235 ) or die "sock: $@"; my $sel = IO::Select->new($sock); while ( my @ready = $sel->can_read(1) ) { for my $fh (@ready) { print "Attempting to read...\n"; # all of these hang! #print Dumper($fh->getlines); #print Dumper($fh->getline); print Dumper(scalar <$fh>); } }

        Note these aren't complete examples as they are oversimplified and lack error handling. Anyway, sure, you could implement your own routine to read the socket byte-by-byte until you've got a full line, but that's a wheel that's been re-implemented a million times (I've done it several times myself). Again: I strongly recommend you use a library that already provides this functionality!