Solved

Problem with Perl networking on Windows XP

Posted on 2010-11-24
4
232 Views
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";
          $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";
        }
    }
}
0
Comment
Question by:bob0206
  • 2
4 Comments
 
LVL 5

Accepted Solution

by:
group0 earned 250 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); 
			}
			next;
		} else {
			print "select() timeout\n";
			if ($thread_stop) {
				print "listening thread shutting down\n";
				$sock->close();
				return 1;
			}
			next;
		}
	}
}

my $thr = threads->create('listen_thread');
sleep(30);
$thread_stop = 1;
$thr->join();
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=>'127.0.0.1',  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 127.0.0.1:58363 - sample udp message
select() timeout
select() timeout
select() timeout
select() timeout
listening thread shutting down
all done

Open in new window

0
 
LVL 5

Expert Comment

by:group0
ID: 35118386
Any update?
0
 
LVL 9

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

Featured Post

Announcing the Most Valuable Experts of 2016

MVEs are more concerned with the satisfaction of those they help than with the considerable points they can earn. They are the types of people you feel privileged to call colleagues. Join us in honoring this amazing group of Experts.

Question has a verified solution.

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

Suggested Solutions

I've just discovered very important differences between Windows an Unix formats in Perl,at least 5.xx.. MOST IMPORTANT: Use Unix file format while saving Your script. otherwise it will have ^M s or smth likely weird in the EOL, Then DO NOT use m…
Checking the Alert Log in AWS RDS Oracle can be a pain through their user interface.  I made a script to download the Alert Log, look for errors, and email me the trace files.  In this article I'll describe what I did and share my script.
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…
Established in 1997, Technology Architects has become one of the most reputable technology solutions companies in the country. TA have been providing businesses with cost effective state-of-the-art solutions and unparalleled service that is designed…

816 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

Need Help in Real-Time?

Connect with top rated Experts

8 Experts available now in Live!

Get 1:1 Help Now