Non-blocking socket access on Windows

April 7th, 2006 at 8:20 am

As I mentioned several times in this blog, one of my most interesting pet-projects at work (actually, a very much work-related pet project that continues to greatly boost my productivity) is a set of tools that communicate on the PCs serial port, thus allowing control of embedded applications and cards with FPGAs or processors.

More details about this topic are here, here and here.

To communicate on the ‘reading’ socket from Perl’s side, I needed a non-blocking read ability because I didn’t want to get into threads. This turned out more difficult than I thought and at one stage I almost gave up because some ActiveState ‘issue reports’ state that non-blocking reads on Windows are problematic. I posted a question on PerlMonks and it got into this discussion.

Eventually, I got this to work. The solution is only two lines of (unintelligible) code:

my $nonblocking = 1;
ioctl($socket, 0x8004667e, \\$nonblocking);

ioctl is a Unix standard C function for controlling IO devices (hence its name - IO control: ioctl). Although it doesn’t exist on Windows per se, it turns out that it was ported for sockets, as part of the Winsock library, which is a port of Unix sockets to Windows. Winsock has a function named ioctlsocket which is a port of ioctl for sockets.

ioctl receives a socket handle, a ‘command’ and a pointer. Based on the command, it either reads what the pointer points to into the device, or writes into the pointer from the device. This is why a reference must be passed as the third argument in Perl.

my $nonblocking = 1;
ioctl($socket, 0x8004667e, $nonblocking); # doesn't work
ioctl($socket, 0x8004667e, 1); # also doesn't work
ioctl($socket, 0x8004667e, \\$nonblocking); # works !

After calling this ioctl on a newly created socket, one can then freely perform non-blocking reads with sysread, which is very convenient if you are in an event loop of some kind (a Tk GUI, for instance) or just aren’t sure how many characters you need to receive from the socket.

Related posts:

  1. once again: perl, serial ports and what’s between them
  2. perl master, C++ slave, bound for serial port programming
  3. parallel programming
  4. Bison looking for bison.simple on Windows
  5. some regex “best practices”

7 Responses to “Non-blocking socket access on Windows”

  1. Greg DonaldsonNo Gravatar Says:

    Eli,

    I am in the process of working to adapt Net::SSH::Perl to run on Win32. One of the items that needed to be updated wqas the non-blocking setup.
    Google led me to your doorstep.

    I have a question the text above says that the first call below and the second call do not work but the third does. I cannot see anything
    different in the third call. What am I missing?

    The paragraph above the examples says that the third parameter has to
    be passed by reference but if this were the case wouldn’t $nonblocking
    be passed as \$nonblocking in the third example.

    my $nonblocking = 1;
    ioctl($socket, 0×8004667e, $nonblocking); # doesn’t work
    ioctl($socket, 0×8004667e, 1); # also doesn’t work
    ioctl($socket, 0×8004667e, $nonblocking); # works !

    Thanks,

    Greg Donaldson
    Rockville, MD

  2. EliNo Gravatar Says:

    Greg - you’re probably right and it should be passed as \$nonblocking. The weblog post has a mistake, which I’ll fix.

  3. DavidNo Gravatar Says:

    2 full days I’ve been looking for this info for ActivePerl on Win32. Tried a million different combinations of other stuff, and those 2 lines solved it (for the most part). Many thanks!

  4. DavidNo Gravatar Says:

    To clarify my previous post,

    my $nonblocking = 1;
    ioctl($socket, 0×8004667e, \$nonblocking);

    are what worked for me. In my implementation, I also had to make sure that I used sysread() instead of read()

  5. EliNo Gravatar Says:

    Thanks, David for the clarification.

  6. elibenNo Gravatar Says:

    I fixed the post. It was a typo as a result of needing two \s (\\) to show a \ in HTML pre tags.

  7. Michael WNo Gravatar Says:

    I’ve spent several days trying to make a script work; this was the magic bullet. Thanks a lot!

Leave a Reply

To post code with preserved formatting, enclose it in `backticks` (even multiple lines)