3

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 &lt 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 ...

smskelley
  • 161
  • 1
  • 7

2 Answers2

4

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";
}
Robert S. Barnes
  • 39,711
  • 30
  • 131
  • 179
  • thanks! though I tried binding to the broadcast address, I'll try something more closely resembling your code to ensure mine is right. – smskelley May 07 '09 at 20:59
  • If you like the answer and it seems to solve your problem could you mark it up and select it as your answer? Thanks! – Robert S. Barnes May 08 '09 at 05:35
1

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().

pts
  • 80,836
  • 20
  • 110
  • 183
  • Definitely check your return values, though its hard to conceive of why recv on a datagram socket would fail. – Bklyn May 02 '09 at 03:50
  • I have checked the return value of recv(..) and $!. there is no return value from recv(..) and $! = 'Unknown Error'. – smskelley May 06 '09 at 14:56