Question

Given that:
The server is on windows xp running ActiveState Perl
The server is connected to an internal network and an external network
A computer on the internal network is broadcasting in udp to 10.4.255.255 on port 9722

I need to:
listen to the broadcast and pass the messages to a function

This is the code I am using:


my $sock;

do {
  eval {
    $sock = IO::Socket::INET->new(LocalPort => 9722, Proto => 'udp')
            or die("Couldn't open the socket: $@");
    1;
  };
  warn($@) and sleep(5) if($@);
} while ($@);

for(my $i = 0;$i < 20;$i++) {
  my $string = 'a';
  $sock->recv($string,1024);
  print &parseInput($string);
}

note that &parseInput returns the original string it was passed.

My problem:
after calling $sock->recv(), $string becomes empty. Using another application I can see that without a doubt there is information being broadcast across 10.4.255.255, but I cannot access it.
if at all possible, I would like to remain using IO::Socket::INET.

edit: I have checked the return value of recv(..) and $!. there is no return value from recv(..) and $! = 'Unknown Error'.

edit 2: I'm trying use Socket; now and have the following:


$proto = getprotobyname('udp');
socket(SOCKET, PF_INET, SOCK_DGRAM, $proto) or die "socket: $!";
setsockopt(SOCKET, SOL_SOCKET, SO_BROADCAST, 1) or die "sockopt: $!";
bind(SOCKET, sockaddr_in(9722, inet_aton('192.168.0.103'))) or die "bind: $!";
recv(SOCKET, $msg, 128, 0) or die "recv: $!";


It generates the error -- recv: Unknown error at ...

Was it helpful?

Solution

I believe I found you're main problem.

The receiver has to bind either to any interface ( INADDR_ANY ) or to the network's broadcast address ( either the all networks one or the directed one ).

Here is example code for both the broadcast sender and receiver.

When using setsockopt watch out! You have to pack the last argument.

#!/usr/bin/perl -w
# broadcast sender script
use strict;
use diagnostics;
use Socket;

my $sock;
my $receiverPort = 9722;
my $senderPort = 9721;

socket($sock, PF_INET, SOCK_DGRAM, getprotobyname('udp'))   || die "socket: $!";
setsockopt($sock, SOL_SOCKET, SO_REUSEADDR, pack("l", 1))   || die "setsockopt: $!";
setsockopt($sock, SOL_SOCKET, SO_BROADCAST, pack("l", 1)) or die "sockopt: $!";
bind($sock, sockaddr_in($senderPort, inet_aton('192.168.2.103')))  || die "bind: $!";

while (1) {
    my $datastring = `date`;
    my $bytes = send($sock, $datastring, 0, 
                     sockaddr_in($receiverPort, inet_aton('192.168.2.255')));
    if (!defined($bytes)) { 
        print("$!\n"); 
    } else { 
        print("sent $bytes bytes\n"); 
    }
    sleep(2);
}

#!/usr/bin/perl -w
# broadcast receiver script
use strict;
use diagnostics;
use Socket;

my $sock;

socket($sock, PF_INET, SOCK_DGRAM, getprotobyname('udp'))   || die "socket: $!";
setsockopt($sock, SOL_SOCKET, SO_REUSEADDR, pack("l", 1))   || die "setsockopt: $!";
bind($sock, sockaddr_in(9722, inet_aton('192.168.2.255')))  || die "bind: $!"; 

# just loop forever listening for packets
while (1) {
    my $datastring = '';
    my $hispaddr = recv($sock, $datastring, 64, 0); # blocking recv
    if (!defined($hispaddr)) {
        print("recv failed: $!\n");
        next;
    }
    print "$datastring";
}

OTHER TIPS

Check the return value of $sock->recv, and print "$!\n". What kind of error message does it print when $string becomes empty? You may have to do $sock->connect(...) or $sock->bind(...) before calling $sock->recv().

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top