in reply to Re^3: How to Multiplex a Client using IO::Select
in thread How to Multiplex a Client using IO::Select

The second and third timeout should be zero. Better yet, you can combine the three system calls into one:

while( 1 ) { if ( my ($readers, $writers, $exceptors) = IO::Select::select($selector, $selector, $selector, 0.1) ) { for( @$readers ) { ## See what they have to say } for( @$writers ) { ## Tell'em what they need to know } for( @$exceptors ) { ## Deal with their tantrums } } if( $Qstdin->pending ) { my $kbinput = $Qstdin->dequeue; ## do whatever } }

Another possible improvement would be to ditch Thread::Queue in favour of a Win32::Socketpair "pipe".

Replies are listed 'Best First'.
Re^5: How to Multiplex a Client using IO::Select
by BrowserUk (Patriarch) on Oct 13, 2008 at 10:40 UTC
    Another possible improvement would be to ditch Thread::Queue in favour of a Win32::Socketpair "pipe".

    I'd be very reluctant to give up what I know works in favour of something, that despite my recognising it's promise, I've yet to get to grips with. Have you tried Win32::Socketpair yet?

    From my view it just adds complications. You still need a thread to handle STDIN, but now you have the problem of passing socket handles around? How would you construct the above snippet?


    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    "Science is about questioning the status quo. Questioning authority".
    In the absence of evidence, opinion is indistinguishable from prejudice.

      How would you construct the above snippet?

      my ($r, $w) = winsocketpair(); $w->autoflush(1); async { print $w $_ while defined( $_ = <STDIN> ); }->detach; while( 1 ) { if ( my ($readers, $writers, $exceptors) = IO::Select::select($selector, $selector, $selector) ) { for( @$readers ) { ## See what they have to say } for( @$writers ) { ## Tell'em what they need to know } for( @$exceptors ) { ## Deal with their tantrums } } }

      Have you tried Win32::Socketpair yet?

      Turns out it crashes :(

      Update: Removing the calls to ioctl removes the crash and makes the module work. I don't know at what cost, though.

        Update: Removing the calls to ioctl removes the crash and makes the module work. I don't know at what cost, though.

        Do you mean the two ioctl calls inside the module? Or were there some in your code above that you've removed?

        If the former, then I think that things may be improved, if not fixed, by changing

        ioctl($client, 0x8004667e, 1);

        to

        my $true = 1; ioctl($client, 0x8004667e, \$true );

        I've certainly had code where a similar change prevented traps in the past. I'm not sure if the same is necessary for the ioctl($client, 0x8004667e, 0); case. I'm still a bit perplexed by the logic in the module, and the need for that latter call?


        Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
        "Science is about questioning the status quo. Questioning authority".
        In the absence of evidence, opinion is indistinguishable from prejudice.
      Win32::Socketpair will only work in windows. i need platform independent one. Thread is ok. I tried below code i faced pblm in windows. The Thread is not detaching for context switch. it rotate in while loop. Correct the below code if i am wrong. Server ======
      use strict; use IO::Socket; use IO::Select; use Sys::Hostname; use constant BUFSIZE => 1024; my $host = hostname; my $port = shift || '10280'; my $socket = new IO::Socket( Domain => PF_INET, Proto => getprotobyname('tcp'), LocalAddr => $host, LocalPort => $port, Listen => 1,#SOMAXCONN, #ReuseAddr => SO_REUSEADDR, ) or die $@; my $buffer; print "Waiting to do service...\n"; while (my $client =$socket->accept) { print "Client: ",$client->peerhost," Connected..\n"; syswrite($client,"Reached Server\n",BUFSIZE); if(sysread($client,$buffer,BUFSIZE)>0) { print "$buffer\n"; } else { print "Client Disconnected..\n"; print "Waiting to do service...\n"; } }
      Client ======
      use strict; use IO::Socket; use IO::Select; use Thread::Queue; use constant BUFSIZE => 1024; my $host = shift or die "Usage: client.pl host [port]\n"; my $port = shift || '10280'; my $socket = new IO::Socket(Domain => PF_INET, PeerAddr => $host, PeerPort => $port, Proto => getprotobyname('tcp'), Timeout => 60,) or die $@; my $readers = IO::Select->new() or die "Can't create IO::Select read o +bject"; #$readers->add(\*STDIN); $readers->add($socket); my $Qstdin = new Thread::Queue; async { $Qstdin->enqueue( $_ ) while defined( $_ = <STDIN> ); }->detach; my $buffer; while (1) { my @readers = $readers->can_read(0.1); foreach my $readservice (@readers) { print "Inside can_read\n"; if(sysread($readservice,$buffer,BUFSIZE)>0) { print "$buffer"; } else { while( $Qstdin->pending ) { my $kbinput = $Qstdin->dequeue; syswrite($readservice,$kbinput."\n",BUFSIZE); } } } }

        Try again once you've added use threads; at the top of your client code. async is a function exported by that module.

        Without it, you should be seeing a error: Can't call method "async" without a package or object reference.


        Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
        "Science is about questioning the status quo. Questioning authority".
        In the absence of evidence, opinion is indistinguishable from prejudice.

        Win32::Socketpair will only work in windows. i need platform independent one

        I know. You can use it conditionally.

        use IO::Handle qw( ); # For autoflush BEGIN { # Override pipe to return something selectable on Windows. if ($^O eq 'MSWin32') { require Win32::Socketpair; require subs; subs->import('pipe'); *pipe = sub { ($_[0], $_[1]) = Win32::Socketpair::winsocketpair() or return; }; } } pipe(my $r, my $w) or die $!; $w->autoflush(1); print $w ("Hello World\n"); print(scalar(<$r>));

        Unfortunately, turns out it crashes on my system.