Solved

Problem with Perl networking on Windows XP

Posted on 2010-11-24
4
233 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

Free Tool: Site Down Detector

Helpful to verify reports of your own downtime, or to double check a downed website you are trying to access.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

Question has a verified solution.

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

Suggested Solutions

Title # Comments Views Activity
Filtering a file to table 9 101
How to strip .csv from file name 9 83
Perl Untar File 1 54
Perl: How to add backslashes to every period in a string 1 32
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.…
In the distant past (last year) I hacked together a little toy that would allow a couple of Manager types to query, preview, and extract data from a number of MongoDB instances, to their tool of choice: Excel (http://dilbert.com/strips/comic/2007-08…
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…

791 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