Beefy Boxes and Bandwidth Generously Provided by pair Networks
laziness, impatience, and hubris
 
PerlMonks  

Sockets and threads, oh my!

by KevinZwack (Chaplain)
on Jun 17, 2006 at 05:22 UTC ( #555941=perlquestion: print w/ replies, xml ) Need Help??
KevinZwack has asked for the wisdom of the Perl Monks concerning the following question:

Hello, I'm trying to write an automated test management tool that drives a device via a TCP/IP socket. I need a listener that runs continuously asynchronously, and occasionally interacts with the sender. Perl threads and the Thread:Queue module would seem to fit the bill nicely. I've written client code based largely on Lincoln Stein's book. I can't get my code to run on Windows (tried pxperl and activestate perl), but it does work on my Solaris8 system. I've created this scrap of code which reproduces the problem. Again, it works on unix but but not windows:
#!/usr/bin/perl5.8.8 -w use strict; use warnings; use threads; use IO::Socket qw(:DEFAULT :crlf); my $host = shift || 'localhost'; my $socket = IO::Socket::INET->new(PeerAddr => $host, PeerPort => 'ftp', Proto => 'tcp', Type => SOCK_STREAM, Timeout => 5) or die "Couldn't connect to remote host: $@\n"; my $listenerThread = threads->create(\&listener, $socket) or die "$@\n +"; while (<STDIN>) { chomp; print $socket $_, CRLF; }; exit(0); sub listener($) { my $s = shift; my $data; $/ = CRLF; syswrite(STDOUT, $data) while sysread($s, $data, 2048); print "\nListener exiting\n"; }; __END__
My program and this snippet always hang up after typing something to STDIN, like "help". Note that I am using the same unix $host in all cases.

Any ideas would be appreciated.

Thanks,
Kevin Zwack

Comment on Sockets and threads, oh my!
Download Code
Re: Sockets and threads, oh my!
by BrowserUk (Pope) on Jun 17, 2006 at 08:54 UTC

    Your socket is in blocking mode which means that you won't be able to write to it until your sysread in the thread times out--which it never will. The solution is to use Tye's method of setting the thread non-blocking

    Update: made the listener detect when the other end disconnected.

    #!/usr/bin/perl5.8.8 -w use strict; use warnings; use threads; use IO::Socket qw(:DEFAULT :crlf); my $host = shift || 'localhost'; my $socket = IO::Socket::INET->new( PeerAddr => $host, PeerPort => 'ftp', Proto => 'tcp', Type => SOCK_STREAM, Timeout => 5 ) or die "Couldn't connect to remote host: $@\n"; ioctl( $socket, 0x8004667e, \1 ); my $listenerThread = threads->create(\&listener, $socket) or die "$@\n +"; while (<STDIN>) { chomp; print $socket $_, CRLF; }; exit(0); sub listener($) { my $s = shift; my $data; $/ = CRLF; while( 1 ) { ## try to read something. my $read = sysread($s, $data, 2048); ## Quit if sysread gave an error (returned undef) other than 1 +0035 ## 10035 => A non-blocking socket operation could not be comp +leted immediately last unless defined $read or 0+$^E == 10035; ## If there was nothing to read, sleep a while and retry sleep 1 and redo unless $read; ## Got something, so display it syswrite(STDOUT, $data); } print "\nListener exiting\n"; }; __END__

    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    Lingua non convalesco, consenesco et abolesco. -- Rule 1 has a caveat! -- Who broke the cabal?
    "Science is about questioning the status quo. Questioning authority".
    In the absence of evidence, opinion is indistinguishable from prejudice.
      I tried your modified code, but it still seems the function the same as before. I'm confused too, aren't sockets supposed to be full-duplex?

      Unfortunately the motherboard on my laptop fried yesterday, so I won't be able to due further testing on Windows. I can continue development on my Solaris workstation for the next few weeks.

      Regards,
      Kevin Zwack

        I can assure you that the code I posted works using AS811/AS817 under XP.

        As for the "full-duplex" thing, that is a confusing term when applied to communications over tcp connections. Both ends can transmit simultaneuosly because the buffering and handshaking (ack & nacks) are taken care of at the ip level. Whether one end can both send and receive simultaneously on different threads really depends upon the implementation.

        What I can tell you is that under XP, if the socket is in blocking mode, attempts to send and receive are serialised by the runtime. Ie. If one thread is currently in a blocking read, no other thread will be able to send until the read is satisfied or it times out. In non-blocking mode, the same is true, but if you use sysread, it will only fetch however much is currently available at the interface and return immediately. Even if nothing is available. The error code I mention in the code indicates that an incomplete read has returned early.

        Whether sockets operate this way on other platforms I do not know.


        Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
        Lingua non convalesco, consenesco et abolesco. -- Rule 1 has a caveat! -- Who broke the cabal?
        "Science is about questioning the status quo. Questioning authority".
        In the absence of evidence, opinion is indistinguishable from prejudice.

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://555941]
Approved by GrandFather
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others scrutinizing the Monastery: (7)
As of 2014-12-25 10:35 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    Is guessing a good strategy for surviving in the IT business?





    Results (160 votes), past polls