Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl: the Markov chain saw
 
PerlMonks  

Non-blocking socket read on Windows

by spurperl (Priest)
on Feb 13, 2006 at 12:51 UTC ( #529812=perlquestion: print w/ replies, xml ) Need Help??
spurperl has asked for the wisdom of the Perl Monks concerning the following question:

Dear monks,

I'm trying to make a Perl script talk in a bi-directional manner with a C++ application using a socket. For this, I want to implement non-blocking socket read. Now, there is the nice IO::select which has the can_read() function. However, can_read() doesn't actually return how much I can read, only that I can. So, I've been reading the Cookbook and the Advanced Perl book, and my options are: (1) use multi-threading and (2) using fcntl() to make sysread() on the socket non-blocking. As you probably know, the nonblocking fcntl() (option 2) doesn't work on Windows, which apparently doesn't support this mode of work with files. I know I can go to option (1), but I would prefer not to - because my script is really quite simple. So, I came up with the following approach (pseudocode):

sub try_read(socket) buf = "" loop if (IO::Select->can_read socket) buf .= sysread(socket, 1); else exit loop return buf
This works, because if can_read says that there's data to read, there's at least one byte there, so I sysread with length 1 and concatenate the byte. When the data ends, the loop ends. Quite, simple.

Problem is, it looks inefficient. If I receive a packet of several KB, this loop will happily run thousands of times, each time calling can_read() and sysread(). However, I don't see any other option for robust non-blocking read on Windows, without using threads.

Any ideas / suggestions / enlightments ?

Thanks in advance

Comment on Non-blocking socket read on Windows
Download Code
Replies are listed 'Best First'.
Re: Non-blocking socket read on Windows
by salva (Abbot) on Feb 13, 2006 at 14:41 UTC
    On Windows, you can use this ioctl call to make the socket non blocking:
    ioctl($socket, 0x8004667e, $nonblocking);

    update: $nonblocking = 1 => makes the socket non blocking, $nonblocking = 0 => makes the socket blocking.

      This solution works admirably !

      After setting the ioctl() command you're suggesting on my socket, I'm reading from it using sysread(), which behaves in a non-blocking way, returning the amount of bytes it has actually read. This overall works much faster than my looping approach, especially for longer messages.

      Although this is probably off-topic, it's curious how the "magic value" of 0x8004667E is created. The "macro" for non-blocking IO in ioctl() is FIONBIO, and its calculation is done thus:

      IOC_IN = 0x80000000h; FIONBIO = IOC_IN + 4 * 65536 + ORD ('f') * 256 + 126;
      I wonder what is the rationale behind this ? Can someone explain how these things work ? Is it portable to just plunge the magic value in my code ?
Re: Non-blocking socket read on Windows
by BrowserUk (Pope) on Feb 13, 2006 at 13:36 UTC

    You might take a look at the Win32::Internet module. In particular, the ControlReceiveTimeout [value], ControlSendTimeout [value], DataReceiveTimeout [value] & DataSendTimeout [value] functions.


    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    Lingua non convalesco, consenesco et abolesco. -- Rule 1 has a caveat! -- Who broke the cabal?
    "Science is about questioning the status quo. Questioning authority".
    In the absence of evidence, opinion is indistinguishable from prejudice.
Re: Non-blocking socket read on Windows
by zentara (Archbishop) on Feb 13, 2006 at 13:33 UTC
    The only mention of this, that I've seen is in "perldoc -q filehandle" , scroll to section " How can I tell whether there's a character waiting on a filehandle?" It describes how to read the amount of bytes to be read on a filehandle, but it is for unix. But maybe its worth a try on Windows, or maybe the ActiveState documentation has some extra docs on how to do this. Their docs are better than the perldocs, for windows.

    I'm not really a human, but I play one on earth. flash japh
Re: Non-blocking socket read on Windows
by eyepopslikeamosquito (Canon) on Feb 13, 2006 at 18:26 UTC
Non-blocking socket read on Windows (WORKS!)
by wilsond (Scribe) on Jan 12, 2009 at 13:10 UTC

    In case anyone reads this these days, setting "Blocking => 0" works in Win32 now. I found this out after reading complaints that it doesn't and not even trying it myself. It works for me. Here's some sample code of what I'm doing with it:

    use IO::Socket::INET; my $server = IO::Socket::INET->new(PeerAddr => '127.0.0.1', PeerPort => 12345, Proto => 'tcp', Blocking => 0); my $buf; while (sysread($server, $buf, 1024)) { $servdata .= $buf; print STDERR qq(READ.\n); } print STDERR qq(END READING FROM SERVER...\n);

    I'm doing more with it, of course, but that's the key parts. I hope it works for everyone else out there. I'm curious to hear if it doesn't.

    BTW, I'm using this in ActivePerl 5.10 and PerlTray 7.3.0

      Ok, I am trying to use Net:SSH or Net::SFTP which 'supposedly' user IO::Socket under the covers..
      but all my debugging info in IO::Socket (including syntax errors, croak, warn and print are never seen.) print()s in Net::SSH::Perl work fine.
      This leads me to believe that the underlying code doesn't handle blocking() correctly as my application hangs on Windows, but works fine on Linux (fedora 10).
      I have an application where I need to code the SFTP code and can't use an external pgm to do it.
      what am I doing wrong?
      How do you debug the libraries you 'use'?
      thanks (activestate perl 5.10.1005 just installed, windows XP 32 bit)
      Sam

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://529812]
Approved by Corion
Front-paged by astaines
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others about the Monastery: (9)
As of 2015-07-07 19:54 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    The top three priorities of my open tasks are (in descending order of likelihood to be worked on) ...









    Results (93 votes), past polls