Still celebrating National IT Professionals Day with 3 months of free Premium Membership. Use Code ITDAY17


Problem with Perl networking on Windows XP

Posted on 2010-11-24
Medium Priority
Last Modified: 2012-05-10
I have been trying to make the following code work without success. TIt is a simple thread waiting on a UDP port. There are 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 servver is sending packets. I ran a Windows program on the same UDP and it worked okay.

I am running on 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_BROADCAST),
                                      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";
          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";
           print "listen thread timeout\n";
Question by:bob0206
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 2

Accepted Solution

group0 earned 1000 total points
ID: 34918854
Is there a special reason you're trying to bind the listening socket to a remote peer address of INADDR_BROADCAST?  If you just want to listen on a single UDP port for messages and then record them, here's a version that should do what you want (IO:Select is overkill in this case):

use strict;
use threads;
use threads::shared;
use IO::Socket::INET;

our $thread_stop : shared;

sub listen_thread {
	my %socket_params;
	$socket_params{'Proto'} = 'udp';
	$socket_params{'LocalPort'} = 48888;
	$socket_params{'Timeout'} = 5;
	my $sock = IO::Socket::INET->new(%socket_params) or die("unable to open socket: $@");

	print "listening thread started\n";
	while (1) {
		my ($buffer, $socket_error);
		my ($rin, $rout, $ein, $eout) = ('', '', '', '');
		vec($rin, fileno($sock), 1) = 1;
		if (select($rout=$rin, undef, $eout=$ein, $socket_params{'Timeout'})) {
			$sock->recv($buffer, 1500);
			if ($buffer) {
				printf("received message from %s:%u - %s\n", $sock->peerhost, $sock->peerport, $buffer); 
		} else {
			print "select() timeout\n";
			if ($thread_stop) {
				print "listening thread shutting down\n";
				return 1;

my $thr = threads->create('listen_thread');
$thread_stop = 1;
print "all done\n";

Open in new window

Here's a tiny sender to test with:

use strict;
use IO::Socket;
my $response = IO::Socket::INET->new(Proto=>'udp', PeerHost=>'',  PeerPort=>48888);
$response->send('sample udp message');

Open in new window

And here's the output:

listening thread started
select() timeout
select() timeout
received message from - sample udp message
select() timeout
select() timeout
select() timeout
select() timeout
listening thread shutting down
all done

Open in new window


Expert Comment

ID: 35118386
Any update?

Expert Comment

by:Suhas .
ID: 37313535
This question has been classified as abandoned and is closed as part of the Cleanup Program. See the recommendation for more details.

Featured Post

On Demand Webinar: Networking for the Cloud Era

Did you know SD-WANs can improve network connectivity? Check out this webinar to learn how an SD-WAN simplified, one-click tool can help you migrate and manage data in the cloud.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

I have been pestered over the years to produce and distribute regular data extracts, and often the request have explicitly requested the data be emailed as an Excel attachement; specifically Excel, as it appears: CSV files confuse (no Red or Green h…
There are many situations when we need to display the data in sorted order. For example: Student details by name or by rank or by total marks etc. If you are working on data driven based projects then you will use sorting techniques very frequently.…
Explain concepts important to validation of email addresses with regular expressions. Applies to most languages/tools that uses regular expressions. Consider email address RFCs: Look at HTML5 form input element (with type=email) regex pattern: T…
Six Sigma Control Plans

688 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question