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

For the next installation of 'difficult and painful network programming', I would like to do a non blocking socket open. My searches turned up any number of nodes on non-blocking reads and non-blocking socket accepts, but everyone seems to assume that if you're the one opening a socket, you're a client that can't do anythng until the server tells you to.

Forking isn't really an option, because some of the computers I"m connecting to will boot me after relatively short timeouts.

Essentially I want some code like this:

my @sockets; foreach ( @hosts ) { push @sockets, IO::Socket->new(blah blah blah); } while ( 1 ) { foreach ( @sockets ) { if ( $_->exists && $_->is_open) { do_stuff($_); } } }

Does anyone know of a solution?

____________________
Jeremy
I didn't believe in evil until I dated it.

Replies are listed 'Best First'.
Re: Non blocking socket open
by tadman (Prior) on Jun 29, 2001 at 12:06 UTC
    How about Non-blocking TCP connections? It's an extension of the IO::Socket class that should do what you want.

    The important part, though, is this call:
    $sock->blocking(0);
    Which according to some discussions does not appear to work under Win32 very well, or at all. YMMV.
      Which according to some discussions does not appear to work under Win32 very well, or at all. YMMV.

      Damn. One of my desires was to make it more cross-platform, not less.

      Thanks for the link.

      ____________________
      Jeremy
      I didn't believe in evil until I dated it.

        Winsock has a way to do nonblocking sockets, too. Perhaps you can take that extension, and conditionally call it or use the Win32 way depending on what OS you find yourself under. Ideally that would be part of the socket extension class discussed earlier.

        The Win32 implementation of connect can return WSAEWOULDBLOCK if "The socket is marked as nonblocking and the connection cannot be completed immediately."

        —John Anecdotal P.S. For years I had a ray-traced image of a wooden block (originally a study in woodgrain texture) stuck on the wall with a caption "WSAEWOODBLOCK". One day someone came into my office and, referring to an error message he had gotten, asked what a WSAEWOULDBLOCK was. I silently pointed to the sign.

        It wouldn't be hard to make blocking(0) work under Win32. The code to change is in the Perl source distribution in ext/IO/IO.xs. This patch needs to be sent to p5p, so if you have the motivation to find the tuits to get that done, then many, many people would be appreciative.

        See the previously noted thread and the follow up for details on solutions and patch ideas.

                - tye (but my friends call me "Tye")
Re: Non blocking socket open
by Rudif (Hermit) on Jun 29, 2001 at 22:00 UTC
    Hi jepri

    I was looking recently for a solution to a somewhat different problem, also on Win2k: read from socket with timeout (so that my client does not block forever when the server does not respond, for whatever reason).

    I found a working solution based on IO::Select. Using the 4-arg select() or the module IO::Select is often mentioned in discussion groups. I found a very helpful discussion with many examples in Sriram Srinivasan's Advanced Perl Programming (the Black Panther book), chapter 12, Networking with Sockets.

    The section "Multiplexing Using select" (page 195-) seems to be close to what you need. In this approach, you don't make the socket non-blocking but you call IO::Select->select() to return you a list of sockets that have something ready to be read.

    HTH

    Rudif

    Update: I just received a copy of Lincoln D.Stein's book 'Network Programming with Perl' - I would add 'Fully Explained', from my first impressions. It has a whole chapter (13) on Non-blocking I/O that might interest you.

    The subject matter is somewhat UNIX-centric, but the author discusses the cross-platform portability (mainly Windows and Mac) in many places. Even so, in my first attempt to run an example from Chapter 13 I had a minor portability problem on Win2k, which I could solve by replacing  use Errno 'EINPROGRESS'; by  use POSIX qw(:errno_h);