http://qs1969.pair.com?node_id=129553


in reply to Simple UDP example anyone?

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'

Replies are listed 'Best First'.
OT: Random useless misnamed Windows constants and cargo-cultism
by Chmrr (Vicar) on Dec 05, 2001 at 17:19 UTC

    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'

Re: Re: Simple UDP example anyone?
by Anonymous Monk on Dec 06, 2001 at 09:34 UTC
    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 :)
Re^2: Simple UDP example anyone?
by Anonymous Monk on Feb 14, 2008 at 17:32 UTC
    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.
        Hi! First i sent it as string (my bad), but know i send it as bytes (the right way).
        $sock->send("\xFF\xFF\xFF\xFFTSource Engine Query\x00");
        But still no answer :/ Been stuck with this like 3 days now:(
      Hmm, strange. I only posted once :(
Re^2: Simple UDP example anyone?
by Anonymous Monk on Feb 14, 2008 at 17:35 UTC
    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