Serveur UDP en écoute de diffusion
-
03-07-2019 - |
Question
Étant donné que:
Le serveur est sur Windows XP sous ActiveState Perl
Le serveur est connecté à un réseau interne et à un réseau externe
Un ordinateur du réseau interne diffuse en udp vers 10.4.255.255 sur le port 9722
J'ai besoin de:
écouter la diffusion et transmettre les messages à une fonction
C'est le code que j'utilise:
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);
}
notez que & ampse; parseInput renvoie la chaîne d'origine à laquelle il a été transmis.
Mon problème:
après avoir appelé $ sock- > recv (), $ string devient vide. En utilisant une autre application, je constate que des informations sont sans aucun doute diffusées via 10.4.255.255, mais je ne peux pas y accéder.
Dans la mesure du possible, j'aimerais continuer à utiliser IO :: Socket :: INET.
edit: J'ai vérifié la valeur de retour de recv (..) et de $ !. il n'y a pas de valeur de retour de recv (..) et $! = 'Erreur inconnue'.
edit 2: j'essaie d'utiliser Socket; maintenant et avoir les éléments suivants:
$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: $!";
Il génère l'erreur - recv: erreur inconnue à ...
La solution
Je pense avoir trouvé votre problème principal.
Le destinataire doit se connecter soit à une interface (INADDR_ANY), soit à l'adresse de diffusion du réseau (réseau unique ou réseau dirigé).
Voici un exemple de code pour l'expéditeur et le destinataire de la diffusion.
Lorsque vous utilisez setsockopt, faites attention! Vous devez emballer le dernier 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";
}
Autres conseils
Vérifiez la valeur de retour de $ sock- > recv
et imprimez "$! \ n"
. Quel type de message d'erreur est-il imprimé lorsque $ string
devient vide? Vous devrez peut-être faire $ sock- > connect (...)
ou $ sock- > bind (...)
avant d'appeler $ sock- > recv ()
.