UDP-сервер прослушивает трансляцию

При том, что:
Сервер на windows xp с запущенным ActiveState Perl
Сервер подключен к внутренней сети и внешней сети
Компьютер во внутренней сети вещает по udp на 10.4.255.255 через порт 9722

Мне нужно:
прослушать трансляцию и передать сообщения функции

Это код, который я использую:


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);
}

обратите внимание, что &parseInput возвращает исходную строку, которую он передал.

Моя проблема:
после вызова $sock->recv() $string становится пустой. Используя другое приложение, я вижу, что информация, без сомнения, передается по 10.4.255.255, но я не могу получить к ней доступ.
Если это вообще возможно, я хотел бы продолжать использовать IO::Socket::INET.

edit: я проверил возвращаемое значение recv(..) и $!. нет возвращаемого значения от recv(..) и $! = 'Неизвестная ошибка'.

редактировать 2: я пытаюсь использовать Socket; теперь и есть следующее:


$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: $!";


Выдает ошибку -- recv: Unknown error at ...


person smskelley    schedule 30.04.2009    source источник


Ответы (2)


Кажется, я обнаружил, что ты главная проблема.

Получатель должен привязываться либо к любому интерфейсу (INADDR_ANY), либо к широковещательному адресу сети (либо ко всем сетям, либо к направленному).

Вот пример кода для широковещательного отправителя и получателя.

Будьте осторожны при использовании setsockopt! Вы должны упаковать последний аргумент.

#!/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";
}
person Robert S. Barnes    schedule 07.05.2009
comment
Благодарность! хотя я пытался привязаться к широковещательному адресу, я попробую что-то более похожее на ваш код, чтобы убедиться, что мой правильный. - person smskelley; 08.05.2009
comment
Если вам нравится ответ, и он, кажется, решает вашу проблему, не могли бы вы отметить его и выбрать в качестве ответа? Спасибо! - person Robert S. Barnes; 08.05.2009

Проверьте возвращаемое значение $sock->recv и print "$!\n". Какое сообщение об ошибке выводится, когда $string становится пустым? Возможно, вам придется выполнить $sock->connect(...) или $sock->bind(...) перед вызовом $sock->recv().

person pts    schedule 01.05.2009
comment
Обязательно проверьте возвращаемые значения, хотя трудно понять, почему recv на сокете дейтаграммы не удастся. - person Bklyn; 02.05.2009
comment
Я проверил возвращаемое значение recv(..) и $!. нет возвращаемого значения от recv(..) и $! = 'Неизвестная ошибка'. - person smskelley; 06.05.2009