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

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.
"Too many [] have been sedated by an oppressive environment of political correctness and risk aversion."
  • Comment on Re^5: How to Multiplex a Client using IO::Select

Replies are listed 'Best First'.
Re^6: How to Multiplex a Client using IO::Select
by ikegami (Patriarch) on Oct 13, 2008 at 13:48 UTC

    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.
        Yes, the two ioctl calls inside the module. And I tried what you suggest and got bad file descriptor errors. Didn't look from what. I didn't care anymore at that point, since the module is obviously not going to be used here.
Re^6: How to Multiplex a Client using IO::Select
by muthuma (Novice) on Oct 13, 2008 at 12:38 UTC
    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.
        After using use thread there is response of context switching.Thank you for your input.

      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.