Randy Osburn wrote:

> Need/purpose...  ActiveState Perl program on Win-XP to broadcast a UDP
> packet (requesting info from a specific hardware device on same subnet), and
> receive UDP broadcast reply from the device.  The MAC address of the
> specific hardware device is included in UDP data.  It works.
> 
> Problem:  The program works perfectly about 1/2 of the time!  Sometimes it
> receives the message perfectly.  Sometimes it just sits indefinitely waiting
> for the packet.  i.e. it missed the packet.  An Etherial packet capture
> always shows that the hardware device DID broadcast the reply, but the Perl
> code apparently didn't get it from the socket.  Etherial is running on same
> PC as the Perl code.  The send packet always goes out ok, and the device
> always replies with it's broadcast.  Why does the perl code randomly miss
> about half of those broadcasts that are definitely on the wire?  Has anyone
> had problems with this?  Is there any issue with the code, or any better way
> to code?

Firstly, UDP is not a guaranteed/reliable protocol, so packet loss is a given.
You should still get a reasonable percentage of the traffic though.  A delay
between receiving and replying may help.

> This was originally written to run on a Linux machine, hence the timeout
> code, which does not appear to work on the PC.  When it fails, the code
> appears sits at the recv, and doesn't time out on the pc.  I can broadcast
> another UDP message from another program, and this program will catch it ok,
> even after missing the broadcast one from the hardware device.  Why does it
> fails sometimes and works properly sometimes?
> 
> Any thoughts or ideas would be greatly appreciated!  Thanks!!

You'll need to do some sort of response to get it to be reliable (or use
TCP instead of UDP).

Try running this from two console windows (start it with an arg first [client]
and then a second one without the arg [server]) and see how it goes for losses :

use strict;
use warnings;
use IO::Socket::INET;
use Time::HiRes qw(usleep);

my $cnt = 25;
if (@ARGV) {    # run as client if arg present

        my $recv = IO::Socket::INET->new(Type => SOCK_DGRAM, ReuseAddr => 1,
          Proto => 'udp', PeerPort  => '45312', LocalPort => '45313') or
          die "new client recv socket: $! ($^E)";

        my $send = IO::Socket::INET->new(Type => SOCK_DGRAM, ReuseAddr => 1,
          Proto => 'udp', PeerAddr  => inet_ntoa (INADDR_BROADCAST),
          Broadcast => 1, PeerPort  => '45312', LocalPort => '45313') or
          die "new client send socket: $! ($^E)";
        
        while (1) {
                my $r;
                $recv->recv($r, 1024) or die "recv: $! ($^E)";
                print "CRECV: $r";

#               usleep 1000000; # add a delay if you like

                my $s = "ECHO: $r";
                $send->send($s) or die "send: $! ($^E)";
                print "CSEND: $s";
                last if $r =~ /^$cnt/;
        }

} else {        # run as server

        my $recv = IO::Socket::INET->new(Type => SOCK_DGRAM, ReuseAddr => 1,
          Proto => 'udp', PeerPort  => '45313', LocalPort => '45312') or
          die "new server recv socket: $! ($^E)";

#       $recv->blocking(0);     # try non-blocking, but doesn't seem to work

        my $send = IO::Socket::INET->new(Type => SOCK_DGRAM, ReuseAddr => 1,
          Proto => 'udp', PeerAddr  => inet_ntoa (INADDR_BROADCAST),
          Broadcast => 1, PeerPort  => '45313',
          LocalPort => '45312') or die "new server send socket: $! ($^E)";
        
        my $p = "some text\n";
        my $seq = 1;
        while (1) {

                $send->send("$seq: $p") or die "send: $! ($^E)";
                print "SSEND $seq: $p";
                while (1) {
                        my $r;
                        $recv->recv($r, 1024) or die "recv: $! ($^E)";
                        if ($r) {
                                print "SRECV: $r";
                                last if $r;
                        } else {
                                print "sleep\n";
                                usleep 10;      # never gets here even when NB
                        }
                }
                last if ++$seq > $cnt;
        }
}

__END__
_______________________________________________
Perl-Win32-Users mailing list
[email protected]
To unsubscribe: http://listserv.ActiveState.com/mailman/mysubs

Reply via email to