Beefy Boxes and Bandwidth Generously Provided by pair Networks
Do you know where your variables are?
 
PerlMonks  

How Do I Do an IP Broadcast in Perl?

by HalNineThousand (Beadle)
on Sep 26, 2010 at 18:46 UTC ( [id://862109]=perlquestion: print w/replies, xml ) Need Help??

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

I read a similar thread that provided an answer that didn't work. I need to find a computer on a LAN. I'll have minimal information, but I can make sure it listens and responds on a socket, so I want to write a program that sends out a broadcast signal on the LAN. The other computer would receive that signal (which would include the IP address) and be able to send a message back saying, "I'm here!"

I can handle the rest, but I don't know how to open a socket and send a broadcast message to the LAN. (I know how to get the subnet and all else, just can't send the broadcast!)

I did find this in another thread:

use IO::Socket; $sock = new IO::Socket::INET ( PeerAddr => '1.1.1.1', PeerPort => '7070', Proto => 'tcp', ); die "Could not create socket: $!\n" unless $sock; print $sock "Hello there!\n"; close($sock);

I did change the IP address to my broadcast address, but could never open that socket. I also tried adding the setting "Type=>SOCK_STREAM" but that didn't help.

How can I use Perl to send a broadcast message to a LAN?

Thanks!

Replies are listed 'Best First'.
Re: How Do I Do an IP Broadcast in Perl?
by bingos (Vicar) on Sep 26, 2010 at 18:52 UTC

    You cannot broadcast using TCP. You will have to use UDP

      I changed the protocol to UDP in the broadcast program and it ran and didn't give me an error or anything. But then when I changed the protocol on the listener to UDP, it kept crashing. I removed the "Listen => 1" and it would run but do nothing.

      Here's the code for the listener:

      use IO::Socket; my $sock = new IO::Socket::INET ( LocalHost => '172.16.7.101', LocalPort => '7070', Proto => 'udp', # Listen => 1, Reuse => 1, 8 ); die "Could not create socket: $!\n" unless $sock; my $new_sock = $sock->accept(); while(<$new_sock>) { print $_; } close($sock);

      So I take it I need to change something to be able to listen on a UDP socket?

        Sockets are bi-directional, so they can all listen for packets. "Listen" tells IO::Socket to listen for incoming connections. UDP is connection-less, so Listen is never used with UDP.

        You have a stray "8" in your argument list.

        Okay, I did more searching and found examples that did not specify the local IP address for the socket using UDP. I removed "LocalHost => '172.16.7.101'" and now it's working fine. I've even tested it with several boxes listening and they all got the same message, so I know it's actually broadcasting.

        Thanks for the help!

Re: How Do I Do an IP Broadcast in Perl?
by oko1 (Deacon) on Sep 27, 2010 at 00:10 UTC

    Perhaps I'm misunderstanding your question, but this doesn't sound like anything unusual. E.g., here's a standard ARP interaction, shown via 'tcpdump':

    0:80:c8:f8:4a:51 ff:ff:ff:ff:ff:ff 42: arp who-has 192.168.99.254 tell + 192.168.99.35 0:80:c8:f8:5c:73 0:80:c8:f8:4a:51 60: arp reply 192.168.99.254 is-at 0 +:80:c8:f8:5c:73

    Note that the call goes out to ff:ff:ff:ff:ff:ff - that's the hardware broadcast address - and you get back a reply with the MAC and the IP, which should tell you that the machine is up (unless, of course, you have some reason to suspect somebody faking those.) At a higher level, you could just use 'ping' (since you already know the IP). Unless you really need that machine to send back text (neither ICMP nor UDP are all that useful in that situation), it seems like either of these approaches would take care of "finding" the machine you're looking for.

    Both of these can be implemented in Perl, but I'm reluctant to start cranking code without feeling like I actually understand what you're trying to do.


    --
    "Language shapes the way we think, and determines what we can think about."
    -- B. L. Whorf
Re: How Do I Do an IP Broadcast in Perl?
by Khen1950fx (Canon) on Sep 27, 2010 at 11:15 UTC
    The documentation gives an example of what you are trying to do. Here it is:
    !/usr/bin/perl use strict; use warnings; use IO::Socket::INET; my $sock = IO::Socket::INET->new( PeerPort => 9999, PeerAddr => inet_ntoa(INADDR_BROADCAST), Proto => 'udp', LocalAddr => 'localhost', Broadcast => 1 ) or die "Can't bind: $@\n";
Re: How Do I Do an IP Broadcast in Perl?
by zentara (Archbishop) on Sep 27, 2010 at 11:40 UTC
    Try these, for simplicity. Start the server as root (UDP requires root privileges, IIRC) , and then run instances of the client.

    udp server

    #!/usr/bin/perl -w # udpqotd - UDP message server use strict; use IO::Socket; my($sock, $newmsg, $hishost, $MAXLEN, $PORTNO); $MAXLEN = 1024; $PORTNO = 5151; $sock = IO::Socket::INET->new( LocalPort => $PORTNO, Proto => 'udp') or die "socket: $@"; print "Awaiting UDP messages on port $PORTNO\n"; while ($sock->recv($newmsg, $MAXLEN)) { my($port, $ipaddr) = sockaddr_in($sock->peername); $hishost = gethostbyaddr($ipaddr, AF_INET); print "Client $hishost said $newmsg\n"; $sock->send("CONFIRMED: $newmsg "); } die "recv: $!"; # You can't use the telnet program to talk to this server. You # have to use a dedicated client.

    udp client

    #!/usr/bin/perl -w # udpmsg - send a message to the udpquotd server use IO::Socket; use strict; my($sock, $msg, $port, $ipaddr, $hishost, $MAXLEN, $PORTNO, $TIMEOUT); $MAXLEN = 1024; $PORTNO = 5151; $TIMEOUT = 5; $sock = IO::Socket::INET->new(Proto => 'udp', PeerPort => $PORTNO, PeerAddr => 'localhost') or die "Creating socket: $!\n"; $msg = 'testmessage'.time; $sock->send($msg) or die "send: $!"; eval { local $SIG{ALRM} = sub { die "alarm time out" }; alarm $TIMEOUT; $sock->recv($msg, $MAXLEN) or die "recv: $!"; alarm 0; 1; # return value from eval on normalcy } or die "recv from localhost timed out after $TIMEOUT seconds.\n"; print "Server $hishost responded $msg\n"; # This time when we create the socket, we supply a peer host and # port at the start, allowing us to omit that information in the send. # We've added an alarm timeout in case the server isn't responsive, # or maybe not even alive. Because recv is a blocking system call that + # may not return, we wrap it in the standard eval block construct # for timing out a blocking operation.

    I'm not really a human, but I play one on earth.
    Old Perl Programmer Haiku ................... flash japh

      How does this relate to what the OP is asking? Your code still relies to the client knowing the servers IP address and won't help him solve his problem. Which (if you read the thread) he did anyway, almost 12 hours before you posted your node, so what's the point? Also:

      UDP requires root privileges, IIRC

      Err, no. Stick to port numbers <1024 >1024 and you can send/receive UDP just fine as an unprivileged user.

      Update: corrected port numbers, thanks Corion for the heads up.


      All dogma is stupid.
        (I know how to get the subnet and all else, just can't send the broadcast!)

        Just showing him a working example of sending the broadcast, and many systems are setup that non-root user access is disallowed for ports < 1024


        I'm not really a human, but I play one on earth.
        Old Perl Programmer Haiku ................... flash japh

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others surveying the Monastery: (4)
As of 2024-04-20 04:34 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found