cog has asked for the wisdom of the Perl Monks concerning the following question:

I have a service which has to accept several connections on the same port (and keep them opened).

I was told that by using IO::Select I could accept the incoming connections like this:

  my ( $read, $write, $exceptions ) = IO::Select->select( $pread, $pwrite, $pexceptions );

Here's a piece of code that illustrates a problem I'm having with this:

#!/usr/bin/perl -w use strict; use IO::Socket; use IO::Select; my $sock=new IO::Socket::INET (Localhost => '127.0.0.1', LocalPort => '4000', Proto => 'tcp', Listen => 5, ReuseAddr => 1, ); die "Socket could not be created. Reason $!" unless $sock; my $pread = IO::Select->new; my $pwrite = IO::Select->new; my $pexceptions = IO::Select->new; $pexceptions->add($sock); while (1) { print "1\n"; my ( $read, $write, $exceptions ) = IO::Select->select( $pread, $pwr +ite, $pexceptions ); print "2\n"; } close($sock);

My understandment from what was explained to me is that the while cycle would go on and on, and that I'd have the original socket in $exceptions when a new connection was arriving; then I'd be able to open the connection and put it in $pread.

At each cycle I'd be able to get all the requests from $read.

The problem is, nothing's happening! And when I say "nothing", I really mean "nothing". The "2\n" is not printed, only the first "1\n".

I have tried a timeout on the select, but in that case I get the while to move on but $exceptions is always empty, even when a client is trying to connect.

What am I doing wrong?

(for the record, my specific problem is that I need a service that needs to answer to many clients, and all those clients have many requests, permanently, so I'd like for them to open only one connection and keep using it, instead of opening a new one at each request; I really need to avoid that)

(also for the record, forking is not a possibility, as there's information that has to be shared)

TIA.

Replies are listed 'Best First'.
Re: IO::Select and sockets
by ikegami (Patriarch) on Dec 29, 2005 at 18:26 UTC

    Why are you adding the socket to (just) $pexceptions? An incomming connection counts as a read. Since you didn't add the socket to $pread, the select won't wake up on an incomming connection. (A broken connection would be an example of an exception.) Add

    $pread->add($sock);

    By the way, why did you make $pread, $pwrite, $read and $write singular? Like $pexceptions and $exceptions, they should be plural since they are lists.

Re: IO::Select and sockets
by runrig (Abbot) on Dec 29, 2005 at 18:04 UTC
    The docs say that the return from the select() method is three array refs, so I don't know why you create 3 IO::Select objects as the arguments. If you are looking for sockets to read from, then you should probably use the can_read() method. The code should be more like:
    my $select = IO::Select->new(); my $sock = IO::Socket->new(...); $select->add($sock); while (my @sockets = $select->can_read()) { ... }
    Update: I'll also throw in a plug for Lincoln Stein's "Network Programming with Perl" book.
      OK, that code doesn't block.

      Trying...

      Hey, I managed to make it work! :-D

      I had tried the can_read before, but only now did it work (probably I was doing something differently than what you suggested).

      Thanks, runrig.

      Since I had a lot of trouble finding this information, I'll put here the script I have working at the moment so that others may solve this problem faster in the future:

      #!/usr/bin/perl -w use strict; use IO::Socket; use IO::Select; my $sock=new IO::Socket::INET (Localhost => '127.0.0.1', LocalPort => '4000', Proto => 'tcp', Listen => 5, ReuseAddr => 1, ); die "Socket could not be created. Reason $!" unless $sock; my $select = IO::Select->new(); $select->add($sock); while (my @sockets = $select->can_read()) { for my $incoming (@sockets) { if ($incoming == $sock) { my $new_sock = $incoming->accept; $select->add($new_sock); } else { print "new guy calling: $incoming\n"; } } } close($sock);
      I have found can_read to be rather useless in practice. can_read allows one to read from sockets without blocking, but one usually needs to also write to sockets without blocking. The select method does that.
        I think it depends whether you're connecting to a service, or creating a service and waiting for connections to it. If I need to do both at the same time, then I'd probably use select(), otherwise, I'll use a can_* method (or maybe I'm missing something and doing it inherently wrong?).
      The docs say that the return from the select() method is three array refs

      From the docs I'm reading:

        select ( READ, WRITE, EXCEPTION [, TIMEOUT ] )

      READ, WRITE and EXCEPTION are either undef or IO::Select objects

        Ooops. My mistake. I was reading the next paragraph about the return values and confusing it with the first paragraph about the arguments (update: need coffee). I never have used that method with IO::Select (I see documentation but I don't see it used in Stein's book either)...I usually just use can_read() (which is also what is mostly used in the book).