Beefy Boxes and Bandwidth Generously Provided by pair Networks
Problems? Is your data what you think it is?
 
PerlMonks  

Problems with INET, Select, and Win32

by bob0206 (Initiate)
on Nov 24, 2010 at 22:23 UTC ( [id://873546]=perlquestion: print w/replies, xml ) Need Help??

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

I have been trying to make the following code work without success. It is a simple thread waiting on a UDP port. I have lots of possible devices that may send packets to the port which are then simply placed in a file (not included here). I have verified that the UDP socket is created (netstat -a) and that the server is the sending the packets to the PC (Wireshark). I ran a Windows program that listened on the same UDP and it worked okay.

I am running Strawberry perl, v 5.12. I am having two problems.

The first is that the can_read never fires except for timeouts. If I take it out, the recv blocks and never completes. As noted above, the sending is working and the port is open. I print out the handles in the function and the one I added is present. I also found that if I give a timeout = 0, can_read returns immediately and the whole routine loops rapidly. The documenation says a value of 0 results in a blocking call.

The second is that when I set $thread_stop (to kill the thread), Perl crashes when I execute the return. The routine I use to kill the thread, sets thread_stop and then does a join on the thread. I am using Visual Studio as my editor and it gets invoked with a runtime exception.

Can someone please look at the following code and tell me what I have done wrong? It looks fine to me and I have been fighting it for days. Thanks

sub listen_thread { $udp_sock = IO::Socket::INET->new(PeerAddr => inet_ntoa(INADDR_BR +OADCAST), Proto => udp, LocalPort => 48888) or die "socket: $@"; my $s = new IO::Select($udp_sock); print "listen thread running\n"; #make sure the handle is registered @ready = $s->handles(); print "handles = \n"; foreach $r (@ready) { print "han: $r\n"; } #enter loop to receive packets while (1) { @ready = $s->can_read(5); print "waiting handles\n"; foreach $r (@ready) { print "rd $r\n"; } #see if we should terminate the thread if ($thread_stop == 1) { print "listen thread terminated\n"; $udp_sock->close; return 1; } # see if something is waiting print "th - $ready[0] - $udp_sock\n"; if ($ready[0] == $udp_sock) { print "th-r-wait\n"; $t = $udp_sock->recv($newmsg, 1400,0); print "th-r-done $t\n"; } else { print "listen thread timeout\n"; } } }

Replies are listed 'Best First'.
Re: Problems with INET, Select, and Win32
by BrowserUk (Patriarch) on Nov 24, 2010 at 22:34 UTC

    Where are these declared?

    $udp_sock @ready $t $thread_stop $newmsg

    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.
Re: Problems with INET, Select, and Win32
by ikegami (Patriarch) on Nov 24, 2010 at 22:39 UTC

    PeerAddr => inet_ntoa(INADDR_BROADCAST),

    That makes no sense for UDP. UDP is connectionless, so the socket has no peer.

    The first is that the can_read never fires except for timeouts. If I take it out, the recv blocks and never completes.

    I don't see why you say that's a problem. can_read should only return if recv won't block, so it appears to be working properly.

    The second is that when I set $thread_stop (to kill the thread), Perl crashes when I execute the return.

    There are really only two possible replies to that:

    • "Oh yeah, exiting a thread always crashes Perl."
    • "Odd, that shouldn't happen."

    Would you care to guess which one it is? Hint: It's not the first. If you can't debug the crash yourself, perhaps you should give us something we can debug.

      Getting rid of the peeraddr = ntoa (INADDR_BROADCAST) fixed the receive problem. I assumed adding this would enable input from any source but it does not. I would assume that what it really means is to take packets only from the broadcast IP address as a source (which would be very odd). thanks for the suggestion.

      As for the crash upon exiting the thread, I get the following message from strawberry perl:

      "Free to wrong pool e64070 not 3f67c8, <STDIN> line 1 during global destruction."

      the pool values change on each run.

        I would assume that what it really means is to take packets only from the broadcast IP address as a source (which would be very odd).

        I'm surprised that you can call connect for a connection-less socket, but I'm not surprised that it would only cause packets to be accepted form the address you specify to accept packets from. Your request was indeed very odd. Maybe you were thinking of INADDR_ANY. As for the crash upon exiting the thread, I get the following message from strawberry perl:

        "Free to wrong pool e64070 not 3f67c8, <STDIN> line 1 during global destruction."

        I can confirm that error message is related to threads. Still have nothing to debug.

Re: Problems with INET, Select, and Win32
by aquarium (Curate) on Nov 25, 2010 at 00:45 UTC
    if you haven't yet heard of it, a utility called netcat is very useful for debugging network applications. it's small and easy to use from command line, able to do either side of connection etc.
    regards a comment that UDP is peerless..i doubt whether this is true. afaik it still makes a connection directly to destination, but the protocol does not guarantee delivery or correct ordering of packets such as provided by TCP. UDP is not broadcast...unless you use a broadcast destination address. all IP traffic has source and destination address and port pairs.
    the hardest line to type correctly is: stty erase ^H

      regards a comment that UDP is peerless..i doubt whether this is true.

      UDP is connectionless. A UDP sockets can send to any address+port, and it can receive from any address+port. Apparently, one can use PeerAddr to limit from whom packets will be accepted, but that's not a property of the protocol.

      UDP is unreliable. It doesn't guarantee notification of delivery failures.

      Those are separate (although related) concepts.

      the protocol does not guarantee delivery

      That goes without saying. No protocols can guarantee delivery. That's impossible. For example, there's no way the protocol can deliver the message if I were to cut the machine's network access.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://873546]
Approved by ikegami
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others studying the Monastery: (6)
As of 2024-04-19 16:25 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found