I'd like to test out UDP broadcast on a very simple network: an old wifi router (WRT54GS) that's not connected to the internet at all, an android tablet, and my macbook:
[Tablet] <\/\/\/\/\/> [Wifi Router] <\/\/\/\/\/> [Macbook]
where the wavy lines indicate wireless connections.
The Macbook has IP address 192.168.1.101, the tablet has IP address 192.168.1.102. The router is 192.168.1.1.
To avoid too much low-level detail, I wanted to use netcat to do my testing. I decided to use port 11011 because it was easy to type.
As a first step, I thought I'd try just making this work from the macbook back to itself. In two terminal windows, I ran these programs
Window 1:
% nc -ul 11011
which I started up first, and then:
Window 2:
% echo 'foo' | nc -v -u 255.255.255.255 11011
Nothing showed up in Window 1. The result in Window 2 was this:
found 0 associations
found 1 connections:
1: flags=82<CONNECTED,PREFERRED>
outif (null)
src 192.168.1.2 port 61985
dst 255.255.255.255 port 11011
rank info not available
I'm fairly certain I'm missing something obvious here. Can someone familiar with nc spot my obvious error?
This is a multi-part answer, gleaned from other SO and SuperUser answers and a bit of guesswork.
Mac-to-mac communication via UDP broadcast over wifi
The first thing is that the mac version of netcat (nc) as of Oct 2018 doesn't support broadcast, so you have to switch to "socat", which is far more general and powerful in what it can send. As for the listening side, what worked for me, eventually, was
Terminal 1: % nc -l -u 11011
What about the sending side? Well, it turns out I needed more information. For instance, trying this with the localhost doesn't work at all, because that particular "interface" (gosh, I hate the overloading of words in CS; as a mathematician, I'd hope that CS people might have learned from our experience what a bad idea this is...) doesn't support broadcast. And how did I learn that? Via ifconfig
, a tool that shows how your network is configured. In my case, the output was this:
lo0: flags=8049<UP,LOOPBACK,RUNNING,MULTICAST> mtu 16384
options=1203<RXCSUM,TXCSUM,TXSTATUS,SW_TIMESTAMP>
inet 127.0.0.1 netmask 0xff000000
inet6 ::1 prefixlen 128
inet6 fe80::1%lo0 prefixlen 64 scopeid 0x1
nd6 options=201<PERFORMNUD,DAD>
gif0: flags=8010<POINTOPOINT,MULTICAST> mtu 1280
stf0: flags=0<> mtu 1280
en0: flags=8863<UP,BROADCAST,SMART,RUNNING,SIMPLEX,MULTICAST> mtu 1500
ether 98:01:a7:8a:6b:35
inet 192.168.1.101 netmask 0xffffff00 broadcast 192.168.1.255
media: autoselect
status: active
en1: flags=963<UP,BROADCAST,SMART,RUNNING,PROMISC,SIMPLEX> mtu 1500
options=60<TSO4,TSO6>
ether 4a:00:05:f3:ac:30
media: autoselect <full-duplex>
status: inactive
en2: flags=963<UP,BROADCAST,SMART,RUNNING,PROMISC,SIMPLEX> mtu 1500
options=60<TSO4,TSO6>
ether 4a:00:05:f3:ac:31
media: autoselect <full-duplex>
status: inactive
bridge0: flags=8863<UP,BROADCAST,SMART,RUNNING,SIMPLEX,MULTICAST> mtu 1500
options=63<RXCSUM,TXCSUM,TSO4,TSO6>
ether 4a:00:05:f3:ac:30
Configuration:
id 0:0:0:0:0:0 priority 0 hellotime 0 fwddelay 0
maxage 0 holdcnt 0 proto stp maxaddr 100 timeout 1200
root id 0:0:0:0:0:0 priority 0 ifcost 0 port 0
ipfilter disabled flags 0x2
member: en1 flags=3<LEARNING,DISCOVER>
ifmaxaddr 0 port 5 priority 0 path cost 0
member: en2 flags=3<LEARNING,DISCOVER>
ifmaxaddr 0 port 6 priority 0 path cost 0
media: <unknown type>
status: inactive
p2p0: flags=8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> mtu 2304
ether 0a:01:a7:8a:6b:35
media: autoselect
status: inactive
awdl0: flags=8943<UP,BROADCAST,RUNNING,PROMISC,SIMPLEX,MULTICAST> mtu 1484
ether 7e:00:76:6d:5c:09
inet6 fe80::7c00:76ff:fe6d:5c09%awdl0 prefixlen 64 scopeid 0x9
nd6 options=201<PERFORMNUD,DAD>
media: autoselect
status: active
utun0: flags=8051<UP,POINTOPOINT,RUNNING,MULTICAST> mtu 2000
inet6 fe80::773a:6d9e:1d47:7502%utun0 prefixlen 64 scopeid 0xa
nd6 options=201<PERFORMNUD,DAD>
most of which means nothing to me. But look at "en0", the ethernet connection to the wireless network (192.168). The data there really tells you something. The flags
tell you that it supports broadcast and multicast. Two lines late, the word broadcast
appears again, followed by 192.168.1.255
, which suggested to me that this might be the right address to which to send broadcast packets.
With that in mind, I tried this:
Terminal 2: % echo -n "TEST" | socat - udp-datagram:192.168.1.255:11011,broadcast
with the result that in Terminal 1, the word TEST
appeared!
When I retyped the same command in Terminal 2, nothing more appeared in Terminal 1; it seems that the "listen" is listening for a single message, for reasons I do not understand. But hey, at least it's getting me somewhere!
Mac to tablet communication
First, on the tablet, I tried to mimic the listening side of the mac version above. The termux version of nc
didn't support the -u
flag, so I had to do something else. I decided to use socat. As a first step, I got it working mac-to-mac (via the wifi router of course). It turns out that to listen for UDP packets, you have to use udp-listen
rather than udp-datagram
, but otherwise it was pretty simple. In the end, it looked like this:
Terminal 1: % socat udp-listen:11011 -
meaning "listen for stuff on port 11011 and copy to standard output", and
Terminal 2: % echo -n "TEST" | socat - udp-datagram:192.168.1.255:11011,broadcast
Together, this got data from Terminal 2 to Terminal 1.
Then I tried it on the tablet. As I mentioned, nc
on the tablet was feeble. But socat
was missing entirely.
I tried it, found it wasn't installed, and installed it.
Once I'd done that, on the Tablet I typed
Tablet: % socat udp-listen:11011 -
and on the mac, in Terminal 2, I once again typed
Terminal 2: echo -n "TEST" | socat - udp-datagram:192.168.1.255:11011,broadcast
and sure enough, the word TEST
appeared on the tablet!
Even better, by reading the docs I found I could use
socat udp:recv:11011 -
which not only listens, but continues to listen, and hence will report multiple UDP packets, one after another. (udp-listen
, by contrast, seems to wait for one packet and then try to communicate back with the sender of that packet, which isn't what I wanted at all.)