Newsgroup: it.comp.lang.perl
Titolo: client e server in uno

Sto tentando di convincere il mio programmino Perl ad aprire un socket
UDP, a mandare un pacchetto in broadcast e mettersi subito dopo in
ascolto delle risposte.
Fino al broadcast ci sono (sebbene i pacchetti vengano spediti da una
porta diversa da quella che gli viene ingiunta...), ma sulla ricezione
no, per il semplice fatto che se faccio girare il programma su due
macchine (UNO e DUE), UNO manda il pacchetto, DUE lo riceve, risponde,
ma... lo intercetta lui stesso!
Pezzo di codice:
use strict;
use Socket;
my $port = 4242;
my $paddr = sockaddr_in ( $port, INADDR_BROADCAST );
socket ( my $SOCK, PF_INET, SOCK_DGRAM, getprotobyname ( 'udp' ) );
setsockopt ( $SOCK, SOL_SOCKET, SO_BROADCAST, 1 );
setsockopt ( $SOCK, SOL_SOCKET, SO_REUSEADDR, 1 );
$msg = "1";
send ( $SOCK, $msg, 0, $paddr );
$paddr = sockaddr_in ( $port, INADDR_ANY );
socket ( $SOCK, PF_INET, SOCK_DGRAM, getprotobyname ( 'udp' ) );
bind ( $SOCK, $paddr );
while ( 1 ) {
	my $other_user = recv ( $SOCK, $msg, 3000, 0 );
	my ( $user_port, $user_ip ) = sockaddr_in ( $other_user );
	print "$user_port, ip = " . inet_ntoa ( $user_ip ) . "\n";
	if ( $msg eq "1" ) {
		$msg = "2";
		send ( $SOCK, $msg, 0, $other_user );
	}
	if ( $msg eq "2" ) {
		print "risposta arrivata!\n";
	}
}
Come gia' detto, $user_port non risulta essere 4242, ma 1025, e gia' qui
non e' una bella cosa...
Ma soprattutto, "risposta arrivata\n" viene stampato sulla macchina che
dovrebbe invece *inviare* la risposta, non *riceverla*! E si che quando
viene stampato $user_ip risulta essere giusto, e che la send viene
applicata sugli stessi dati del pacchetto che arriva.
Al piu', potrei capire se UNO non ricevesse la risposta a causa della
porta sbagliata su cui e' in ascolto (cosa che comunque non riesco a
capire...), ma non comprendo perche' sia DUE a leggere il pacchetto.
Suggerimenti in merito?
Grazie :-)
-- 
Roberto -MadBob- Guido
mail bob4mail***@***
gmail.com
web 
http://madbob.homelinux.com
BrainTop Project maintainer - 
http://braintop.sf.net

 Grazie :-)
Non posso fare alcuna prova, pero' di sicuro quando fai send() non sei in
ascolto su alcuna porta UDP, quindi una call a bind() la devi fare prima
di send().
Inoltre proprio perche' non hai fatto bind() prima di send il sistema usa
la syscall sendto() e come source port ne mette una random.
Quindi penso che devi avere:
$paddr0 = sockaddr_in ( $port, INADDR_ANY );
per chiamare socket() + bind()
e $paddr1 = sockaddr_in ( $port, INADDR_BROADCAST );
per fare send() ma con la stessa socket ottenuta, cosi' dovresti
(ma non ho provato) inviare con source addr l' IP dell' interfaccia scelta
dal sistema in base al routing, con sourceport la 4242 destport quella che
metti in $paddr1 e con IP destinatario Broadcast e conseguentemente
anche la macchina trasmittente dovrebbe ricevere il pacchetto con la
prossima recv().
Prova e fai sapere. Magari ripristino una piatteforma per provare anche io,
per ora non posso.
ciao.
Roberto
-- 
questo articolo e` stato inviato via web dal servizio gratuito 
http://www.newsland.it/news
 segnala gli abusi ad 
ab...@newsland.it


Bingo: in questo modo funziona l'associazione alla porta di partenza, ma
comunque l'host che dovrebbe inviare la risposta se la intercetta da
solo (sebbene sia esplicitamente inviata all'IP dell'altro, quello che
ha fatto il broadcast, usando, come visto nel precedente post, gli
stessi dati del pacchetto in merito).
Per ora, grazie :-)
