Beefy Boxes and Bandwidth Generously Provided by pair Networks
No such thing as a small change
 
PerlMonks  

UDP-Broadcast with socket

by strat (Canon)
on Jan 12, 2009 at 17:19 UTC ( [id://735745]=perlquestion: print w/replies, xml ) Need Help??

strat has asked for the wisdom of the Perl Monks concerning the following question:

Update: added client script, changed INADDR_BROADCAST to INADDR_ANY for server (thanks @ikegami)

Good day,

a friend of mine asked me how UDP-Broadcasts with Socket worked. I hardly know anything about UDP, but I tried to learn a little bit about and wrote the following two pieces of code:

server.pl
#! /usr/bin/perl use warnings; use strict; use Socket qw(:all); $|++; # no suffering from buffering my $udp_port = 9999; socket( UDPSOCK, PF_INET, SOCK_DGRAM, getprotobyname('udp') ) or die " +socket: $!"; select( ( select(UDPSOCK), $|=1 )[0] ); # no suffering from buffering setsockopt( UDPSOCK, SOL_SOCKET, SO_REUSEADDR, 1 ) or die "setsockopt SO_REUSEADDR: $!"; setsockopt( UDPSOCK, SOL_SOCKET, SO_BROADCAST, 1 ) or die "setsockopt SO_BROADCAST: $!"; my $broadcastAddr = sockaddr_in( $udp_port, INADDR_ANY ); bind( UDPSOCK, $broadcastAddr ) or die "bind failed: $!\n"; my $input; while( my $addr = recv( UDPSOCK, $input, 4096, 0 ) ) { print "$addr => $input\n"; }
Client.pl:
use warnings; use strict; use Socket qw(:all); use POSIX ":sys_wait_h"; socket( SOCKET, PF_INET, SOCK_DGRAM, getprotobyname("udp") ) or die "Error: can't create an udp socket: $!\n"; select( ( select(SOCKET), $|=1 )[0] ); # no suffering from buffering my $broadcastAddr = sockaddr_in( 9999, INADDR_BROADCAST ); setsockopt( SOCKET, SOL_SOCKET, SO_BROADCAST, 1 ); send( SOCKET, "I'm here", 0, $broadcastAddr ) or die "Error at sendding: $!\n"; close SOCKET;

But the server waits forever, it doesn't get any message from client.pl. I started the scripts on the same PC, an OpenSuse 10.3 Linux with perl5.8.

Please, can you give me a hint what I'm doing wrong? I searched perlmonks and google, but couldn't find anything helpful.

Best regards,
perl -e "s>>*F>e=>y)\*martinF)stronat)=>print,print v8.8.8.32.11.32"

Replies are listed 'Best First'.
Re: UDP-Broadcast with socket
by ikegami (Patriarch) on Jan 12, 2009 at 17:30 UTC

    I think you're suppose to send to INADDR_BROADCAST but listen on INADDR_ANY (or whatever) as normal.

    Your seem to have posted your server code twice?

    By the way, IO::Socket::INET provides a cleaner interface.

Re: UDP-Broadcast with socket
by zentara (Archbishop) on Jan 12, 2009 at 17:40 UTC
    Just in case you are in a hurry....here is a working server/client.
    #!/usr/bin/perl use warnings; use strict; use IO::Socket::INET; print "\n>>Server Program <<\n"; #-- #-- server.pl #-- # Create a new socket my $MySocket=new IO::Socket::INET->new(LocalPort=>1234, Proto=>'udp'); # Keep receiving messages from client my $def_msg="\nReceiving message from client.....\n"; my $text = ""; while(1) { $MySocket->recv($text,128); if($text ne '') { print "\nReceived message '", $text,"'\n"; } # If client message is empty exit else { print "Client has exited!"; exit 1; } }
    #!/usr/bin/perl use warnings; use strict; use IO::Socket::INET; print "\n>>Client Program <<\n"; #-- #-- client.pl #-- # Create a new socket my $MySocket=new IO::Socket::INET->new(PeerPort=>1234, Proto=>'udp', PeerAddr=>'localhost' ); # Send messages my $def_msg="Enter message to send to server : "; my $msg = ""; print "\n",$def_msg; while($msg=<STDIN>) { chomp $msg; if($msg ne '') { print "\nSending message '",$msg,"'"; if($MySocket->send($msg)) { print ".....<done>","\n"; print $def_msg; } } else { # Send an empty message to server and exit $MySocket->send(''); exit 1; } }

    I'm not really a human, but I play one on earth Remember How Lucky You Are
      The OP said he wanted to see how broadcasts worked, but that doesn't use broadcasts.
Re: UDP-Broadcast with socket
by puudeli (Pilgrim) on Jan 12, 2009 at 19:32 UTC

    You really shouldn't send broadcasts since they clutter the network and can be considered intrusive. If you have a valid reason to use broadcasts you really should open a socket for sending with INADDR_BROADCAST. On the server side you can catch the broadcasts by listening to the broadcast address or INADDR_ANY.

    --
    seek $her, $from, $everywhere if exists $true{love};

      Thank you very much

      I followed your advice, but somehow the send doesn't reach the server (on the same host). The network is fine, and Ikegamis script works perfect (except that it is not broadcasting).

      server.pl:

      #! /usr/bin/perl use warnings; use strict; use Socket qw(:all); $|++; # no suffering from buffering my $udp_port = 9999; socket( UDPSOCK, PF_INET, SOCK_DGRAM, getprotobyname('udp') ) or die " +socket: $!"; select( ( select(UDPSOCK), $|=1 )[0] ); # no suffering from buffering setsockopt( UDPSOCK, SOL_SOCKET, SO_REUSEADDR, 1 ) or die "setsockopt SO_REUSEADDR: $!"; #setsockopt( UDPSOCK, SOL_SOCKET, SO_BROADCAST, 1 ) # or die "setsockopt SO_BROADCAST: $!"; # my $broadcastAddr = sockaddr_in( $udp_port, INADDR_BROADCAST ); my $broadcastAddr = sockaddr_in( $udp_port, INADDR_ANY ); bind( UDPSOCK, $broadcastAddr ) or die "bind failed: $!\n"; my $input; while( my $addr = recv( UDPSOCK, $input, 4096, 0 ) ) { print "$addr => $input\n"; }

      Client.pl

      #! /usr/bin/perl use warnings; use strict; use Socket qw(:all); use POSIX ":sys_wait_h"; socket( SOCKET, PF_INET, SOCK_DGRAM, getprotobyname("udp") ) or die "Error: can't create an udp socket: $!\n"; select( ( select(SOCKET), $|=1 )[0] ); # no suffering from buffering my $broadcastAddr = sockaddr_in( 9999, INADDR_BROADCAST ); setsockopt( SOCKET, SOL_SOCKET, SO_BROADCAST, 1 ); send( SOCKET, "a" x 4096, 0, $broadcastAddr ) or die "Error at sendding: $!\n"; close SOCKET;

      Does anybody know what I'm doing wrong?

      My friend intends to use broadcasts to announce a new server going online to a central service. He won't misuse it. I am interested in this topic, because I know a little bit about TCP/IP, but have hardly any knowledge about UDP and broadcasts.

      Best regards,
      perl -e "s>>*F>e=>y)\*martinF)stronat)=>print,print v8.8.8.32.11.32"

        I followed your advice, but somehow the send doesn't reach the server (on the same host). The network is fine, and Ikegamis script works perfect (except that it is not broadcasting).

        I believe on linux, you need to have root priviledges to use UDP broadcast, try running it as root.


        I'm not really a human, but I play one on earth Remember How Lucky You Are
        Does anybody know what I'm doing wrong?

        Knowing I am not doing, just guessing. Your scripts works fine on my box, Fedora7 with perl 5.8.8, I have verified that via capturing the traffic with wireshark. Have you checked your iptables (or firewall) settings?

Re: UDP-Broadcast with socket
by zwon (Abbot) on Jan 12, 2009 at 19:21 UTC

    Both your programs call recv but who supposed to send?

    Update: Ops, ikegami is right, it's server code twice. BTW, there's no need to set SO_BROADCAST on receiving side, it should be set on sender.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://735745]
Approved by Corion
Front-paged by Old_Gray_Bear
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others studying the Monastery: (9)
As of 2024-04-23 11:23 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found