http://qs321.pair.com?node_id=129521

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

I've been looking for a simple UDP example, but have found a dozen of TCP examples merely mentioning UDP... I just want to see a simple UDP example, using IO::Socket. I'm trying to send a single line of data to another server to a specific port and after the server has received the correct data, the server should send back some data and my computer should receive it. It's simple, but I'm puzzled... TCP was easy when I tried it, but UDP isn't and I'm forced to use it (as the server uses it). Therefore, I seek the wisdom from the monastery :)

Replies are listed 'Best First'.
Re: Simple UDP example anyone?
by chromatic (Archbishop) on Dec 05, 2001 at 11:27 UTC
    Recipe 17.5 of the Perl Cookbook is handy:
    use IO::Socket; use strict; my $sock = IO::Socket::INET->new( Proto => 'udp', PeerPort => 5000, PeerAddr => 'hostname', ) or die "Could not create socket: $!\n"; $sock->send('a file to have your advice') or die "Send error: $!\n";
    perlipc has other examples. IO::Socket is slightly easier than Socket, and translating between the two isn't terribly difficult.
      $sock->send('a file to have your advice')
      Now thats what I call a datagram with a message.

      lol, chromatic++

      mitd-Made in the Dark
      'Interactive! Paper tape is interactive!
      If you don't believe me I can show you my paper cut scars!'

      What few people mention is that IO::Socket doesn't work under Solaris (I believe that Sun has hardcoded the constants to non-standard values or similar rubbish) and you get stuck with using Socket

      Ea :wq

        IO::Socket actually does work under Solaris. I've been using it for XML servers on 4 different Solaris boxes ranging from 5.6 to 5.8. It's actually really sweet.
Re: Simple UDP example anyone?
by Chmrr (Vicar) on Dec 05, 2001 at 12:54 UTC

    The question you've asked is two-part -- you want to both send and recieve a UDP message. chromatic addressed the former already, so I'll supply the latter. Here's a short script, using IO::Socket, which sends a UDP packet to some server, and then listens and prints out one (and one only) UDP packet that it gets in response.

    #!/usr/bin/perl -w $|++; use strict; use IO::Socket; my $response = IO::Socket::INET->new(Proto=>"udp",LocalPort=>2424) or die "Can't make UDP server: $@"; my $message = IO::Socket::INET->new(Proto=>"udp",PeerPort=>4242,PeerAd +dr=>"chmrr.mit.edu") or die "Can't make UDP socket: $@"; $message->send("Ping!"); my ($datagram,$flags); $response->recv($datagram,42,$flags); print "Got message from ", $response->peerhost,", flags ",$flags || "n +one",": $datagram\n";

    One thing to note is that we make the server to catch the response before we send out our query -- that way, the response can't "fall between the cracks," so to speak; it can't come back before we have the server up and ready. Another thing to note is that the "42" in there is the maximum length of the packet that the server will read. So if you get more data than this, it'll get truncated. Thus, you might want to make this rather big if you don't know how much data you'll be getting.

    Just for kicks, I'll leave the above-mentioned computer (chmrr.mit.edu) running a UDP server on port 4242 so y'all can send it messages ad nauseum. ;> Here are the basics of the "server" that I'm running -- except the return UDP packet that you'll actually get may be more interesting than just "PONG!" Tip: Run it more than once. ;>

    Update: I took it down, so you'll have to send UDP messages to yourself if you want to test it.

    #!/usr/bin/perl -w $|++; use strict; use IO::Socket; my $server = IO::Socket::INET->new(LocalPort=>4242,Proto=>"udp") or die "Can't create UDP server: $@"; my ($datagram,$flags); while ($server->recv($datagram,42,$flags)) { my $ipaddr = $server->peerhost; print "Oooh -- udp from $ipaddr, flags ",$flags || "none",": $datagr +am\n"; my $response = IO::Socket::INET->new(Proto=>"udp",PeerHost=>$ipaddr, +PeerPort=>2424); $response->send("PONG!"); }

    perl -pe '"I lo*`+$^X$\"$]!$/"=~m%(.*)%s;$_=$1;y^+*`^ ve^#$&V"+@( NO CARRIER'

      Yeah, I'm responding to my own post. This is because what follows is really a rather off-topic rant on my part, and not really related to the question asked above.

      So I got vaguely interested in figuring out what exactly that useless-looking $flags variable was there for. I quickly learned that, unlike $datagram, it's not modified by send or recv, as I had anticipated. Rather, it's says "make me a packet with this set of flags" or "do this special thing when trolling for packets."

      It just happens that one of the machines that I tested my UDP code on was a machine running Windows and ActivePerl. So I started poking around, looking at which constant values for the flags were defined. Under Windows, I found exactly four: MSG_OOB, MSG_PEEK, MSG_DONTROUTE, and MSG_MAXIOVLEN. These, of course, were nicely mysterious to me, so I set out to see what I could see about each:

      • MSG_OOB is supposed to be a flag which signals "urgent" or "priority" messages. It's what catches control-C in Telnet connections, for example. When used with recv, it serves as a filter, only recv'ing "priority" packets. It doesn't work with UDP, though.
      • MSG_PEEK allows you to recv the first packet without taking it off of the server's stack of waiting packets. This is of dubious usefulness, but actually works under windows.
      • MSG_DONTROUTE probably does what it implies. I didn't have much way to test this.

      And this brings me to my main victim -- MSG_MAXIOVLEN. Not only does it have the most ugly-looking name, it's apparently only defined under Windows. A Google search for it shows up a decent number of hits -- but upon careful perusal, every one of them defines it as a constant with no comment after it. In fact, the Winsock specification does the exact same thing -- defined, with no comment, and never refenced again. In an example of huge-scale cargo-cultism, hundreds of header files, including every Windows-based Perl install out there, have copied an absolutly useless constant which is not implemented or described anywhere. A little further reasearch shows that it might be implemented on the UNICOS/mk cray operating system. And even if it is, it's misnamed, as it's not a flag on a message at all, but an arbitrary constant of the TCP stack!

      So there's the sordid tale of a misnamed, unimplmented, useless, but omnipresent constant. Gah!

      perl -pe '"I lo*`+$^X$\"$]!$/"=~m%(.*)%s;$_=$1;y^+*`^ ve^#$&V"+@( NO CARRIER'

      Thanks for the help! The examples were simple and I now have my program working correctly :). These are probably the clearest and the best examples around. But one thing was missing from all these examples... remember timeouts? Timeouts are nice. The recv waits for data till the end of times if the target host was down. Don't forget that :)
      Hi! I've been looking for UDP exampels as well, and i finally found it here! Thanks! But i'm having some problems with your send/receive script:( In my case i'm trying to query a game server (TF2). It runs on port 27015, so i changed PeerPort to 27015 and PeerAddr to my server ip. To get A2S_INFO (number of players, map, server name etc) i have to send a request UDP packet with the following info: "FF FF FF FF 54 53 6F 75 72 63 65 20 45 6E 67 69 6E 65 20 51 75 65 72 79 00 Source Engine Query". When the server gets this packet is should respond by sending this server info back. However, when i run the script nothing happens. It doesn't print anything:( I'm not sure about the LocalPort.. Nevertheless, i've been stuck with this for a long time now, and no one can help me out. Therefore i seek the wisdom of the monks. Thanks in advance! Url to the query protocol for those who are interested: http://developer.valvesoftware.com/wiki/Server_Queries
        Are you sending that as a string, or are you 'pack'ing the bytes? Post your code for constructing the packet.
        Hmm, strange. I only posted once :(
      Hi! I've been looking for UDP exampels as well, and i finally found it here! Thanks! But i'm having some problems with your send/receive script:( In my case i'm trying to query a game server (TF2). It runs on port 27015, so i changed PeerPort to 27015 and PeerAddr to my server ip. To get A2S_INFO (number of players, map, server name etc) i have to send a request UDP packet with the following info: FF FF FF FF 54 53 6F 75 72 63 65 20 45 6E 67 69 6E 65 20 51 75 65 72 79 00 Source Engine Query . When the server gets this packet is should respond by sending this server info back. However, when i run the script nothing happens. It doesn't print anything:( I'm not sure about the LocalPort.. Nevertheless, i've been stuck with this for a long time now, and no one can help me out. Therefore i seek the wisdom of the monks. Thanks in advance! Url to the query protocol for those who are interested: http://developer.valvesoftware.com/wiki/Server_Queries
Re: Simple UDP example anyone?
by Rex(Wrecks) (Curate) on Dec 06, 2001 at 00:03 UTC
    Again, I point to the (IMHO) definitive guide to Perl and Networks --> Network Programming with Perl by Lincoln D. Stein.

    It has several really good UDP samples with very well explained and documented walkthroughs

    "Nothing is sure but death and taxes" I say combine the two and its death to all taxes!
      Yup, also one of my favorite perl reads. Highly recommended for all kinds of perl network-type tasks. There's a whole chapter devoted to the UDP protocol (chapter 18 I think...).
A reply falls below the community's threshold of quality. You may see it by logging in.