in reply to Timeout Socket recv on UDP... on windows

I can't use alarm on Windows systems,

You can:

print time; eval{ local $SIG{ ALRM } = sub { print "time to get up", time; die}; alarm( 10 ); sleep 20; }; alarm( 0 ); print time;; 1201323436 time to get up 1201323446 1201323446 [0] Perl> print $^O, $];; MSWin32 5.008006

Though it probably won't interupt a socket waitstate unless you disable SAFE_SIGNALS.

For how to set a socket non-blocking of windows, do a super search for "0x8004667e".


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."

Replies are listed 'Best First'.
Re^2: Timeout Socket recv on UDP... on windows
by quester (Vicar) on Jan 26, 2008 at 06:11 UTC
    IMHO... it would be preferable to at least mention the symbolic name of the constant, FIONBIO in this case, in preference to just giving the value as 0x8004667e. Otherwise, we risk giving even more Perl newbies the idea that it's cool to write code with mysterious, arbitrary large hex constants in it.

    Perl code is scary* enough to users, even without making it look like we are trying to sneak a concealed Dark Ritual Invocation of the Name of the Beast into our code.

    * Alas, "scary" is exact word my boss used yesterday when he looked at a one-liner I dashed off for him. That's bad, very bad....

      I'm not at all sure that an arbitrary collection of 7 uppercase letters is any better.

      It would only turn up 9 of the 33 posts the search term I gave turns up. And I'm not sure that 9 are relevant. The 33 definitely are. It's very unlikely that number would turn up in any other context.

      And I'm not sure that it would do anything to help them. As that symbolic constant isn't available to them from Perl.

      And I'm not sure it would help them work out the value they need either. Even if they have the relevant C header files, FIONBIO is defined there as:

      #define FIONBIO _IOW('f', 126, u_long) /* set/clear non-blocking i +/o */

      And the relevant parts of that are defined as:

      #define _IOW(x,y,t) (IOC_IN|(((long)sizeof(t)&IOCPARM_MASK)<<16)|( +(x)<<8)|(y)) #define IOCPARM_MASK 0x7f #define IOC_IN 0x80000000 /* copy in parameters */

      Now, I think I'm pretty offay with C and bit-twiddling, but I'm not sure that I could work out what the required number is from that lot.

      And I'm not at all sure that I could recreate that math in Perl.

      That's a lot of "not sures". I am sure that if I use the hex constant, it finds the posts. And works.


      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.
        True, there is little about the string "FIONBIO" in Perl, and your rant about the perverse tastes of the writers of the C header code is on the mark.

        However, including the conventional name of the symbol, even as a comment, allows you to seach for the documentation of the corresponding driver code. For instance, a Google search for "fionbio ioctl site:microsoft.com" finds an MSDN article on "Winsock IOCTLs". In Linux-land, "fionbio driver source" turns up Chapter 6 of the Linux Device Driver book.

Re^2: Timeout Socket recv on UDP... on windows
by shunyun (Novice) on Jan 26, 2008 at 16:05 UTC
    Thanks for the reply, all. I searched through the threads you referenced and saw good examples of setting non-blocking mode. I'm not sure I'm using this right, tho. If I place the statement after establishing the socket and before the while statement (while recv), the receive evaluates false and the while statement doesn't execute.

    my $hSocket = IO::Socket::INET->new( LocalPort=>$intListenPort, Proto=>$strProtocol ) or die "Can't create UDP socket: $@"; ioctl($hSocket, 0x8004667e, pack("I", 1)); my ($datagram,$flags); # Wait for a datagram, then open a response port, respond, then close both ports. while ($hSocket->recv($datagram,42,$flags)) { ...
    So, I'm wondering if this is the right approach. I think the core of the problem is that I'm waiting for incoming data to determine if a connection has been established.

    Is there another way to watch for client connection (and corresponding technique to time-out), before establishing the recv loop? For instance, doesn't IO::Socket call an accept method on connection? So couldn't I check $hSocket for a value (undef?) until timeout, and then launch the recv loop once I have a client? Or maybe using the accept method directly, like

    until ($hSocket->accept()) { ...check for timeout ...close socket and exit if timeout } while ($hSocket->recv($datagram,42,$flags)) { ...

    I guess I'm asking if blocking is really the problem or my approach to checking for connection. I think...

      Caveat: I've had little occasion to do much with udp sockets. See also Perl Cookbook (I hope that is a sanctioned link)

      However, udp is connectionless, so you do not need an accept loop. Essentially you want to wait for upto a specified number of seconds for a datagram to arrive and do something else if not. So,

      my $hSocket = IO::Socket::INET->new( LocalPort=>$intListenPort, Proto=>$strProtocol ) or die "Can't create UDP socket: $@"; ioctl($hSocket, 0x8004667e, pack("I", 1)); my( $gotone, $datagram, $flags) = 0; my $endtime = time() + $timeout; while( time() < $endtime ) { sleep 1 and next unless $hSocket->recv($datagram,42,$flags ); ## Got a datagram. ... $gotone = 1; last; } if( $gotone ) { ## We processed a datagram within the timelimit } else { ## we didn't }

      There are probably better ways of structuring that. And you could probably use select or IO::Select to achieve a similar thing.

      Or threads.


      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.