Communication between devices that doesn’t require a server (UDP code examples)
UDP broadcast
Two things to keep in mind about UDP broadcast:
- UDP broadcast is not a safe method. There is no check if anyone has received the packet. It is just sent out on the network and that’s it. If a recipient miss it, no warning or error is thrown.
- UDP broadcast works only in your local network. You cannot send a UDP broadcast to “the world”. ISPs, modems and specially mobile networks do not allow it.
UDP broadcast sender example for ESP8266
This code snippet shows how to initialize and use a simple UDP broadcast sender for the ESP8266.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
#include <WiFiUDP.h> /** WiFiUDP class for creating UDP communication */ WiFiUDP udpBroadCaster; /** IP address of this module */ IPAddress ipAddr (192, 168, 0, 10); // replace with your module IP address /** Network address mask for UDP multicast messaging */ static IPAddress multiIP (192, 168, 0, 255); // replace with your network mask /** UDP broadcast port */ static const int udpBcPort = 9997; // replace with your port number /** sendUDPBroadCast send String broadcast over LAN by UDP broadcast */ void sendUDPBroadCast(String broadCast) { // Broadcast per UDP to LAN udpBroadCaster.beginPacketMulticast(multiIP, udpBcPort, ipAddr); udpBroadCaster.print(broadCast); udpBroadCaster.endPacket(); udpBroadCaster.stop(); } |
This is a very simplified example of an UDP broadcaster. As I am sending only status messages, which are JSON objects converted to ASCII strings, the only argument for the function is a String. If you want to send binary data, you would need to adapt this.
The function used is call beginPacketMulticast, which is in my opinion a wrong name, because there is a difference between UDP Multicast and UDP Broadcast. For multicast, the packet is sent only to a list of IP addresses that are registered to the multicast, while broadcast means the packet is just sent out and whoever’s IP address matches the mask can receive it. But that’s how it is defined in the ESP8266 Arduino framework.
All needed is the WiFiUDP class, the local IP address, the multicast mask (equals broadcast mask) and the UDP port. udpBroadCaster.beginPacketMulticast() starts the communication on a specific port, udpBroadCaster.print() sends the payload (can be repeated if several packets are combined in one broadcast), udpBroadCaster.endPacket() finishes the sending and udpBroadCaster.stop() ends the communication and frees up the used UDP port.
UDP broadcast listener example for ESP8266
The listener code for UDP broadcasts is very simple as well.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
#include <WiFiUDP.h> /** UDP broadcast port */ static const int udpBcPort = 9997; /** WiFiUDP class for listening to UDP broadcasts */ extern WiFiUDP udpListener; void setup(void) { // Some initialization stuff // Start UDP listener udpListener.begin(udpBcPort); } void loop(void) { // here is your code that is processed in a loop // Check if broadcast arrived int udpMsgLength = udpListener.parsePacket(); if (udpMsgLength != 0) { byte udpPacket[udpMsgLength+1]; // reserve a local buffer IPAddress udpIP = udpListener.remoteIP(); // Read the received payload into the local buffer udpListener.read(udpPacket, udpMsgLength); udpPacket[udpMsgLength] = 0; udpListener.flush(); // empty UDP buffer for next packet String debugMsg = "UDP broadcast from "; debugMsg += "Sender IP: " + String(udpIP[0]) + "." + String(udpIP[1]) + "." + String(udpIP[2]) + "." + String(udpIP[3]); debugMsg += "\n Msg: " + String((char *)udpPacket); Serial.println(debugMsg); } } |
Listening to a specific UDP port is initialized in setup() by calling udpListener.begin(udpBcPort);.
In the loop() we then just check if a package has arrived and parse it.
UDP broadcast sender example for ESP32
This code snippet shows how to initialize and use a simple UDP broadcast sender for the ESP32.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 |
#include <WiFiUdp.h> /** * udpSendMessage * Send a message over UDP * * @param ipAddr * receiver IP address * @param udpMsg * payload to be send * @param udpPort * port to be used to send * @return <code>bool</bool> * true if payload could be sent * false if error occurs */ bool udpSendMessage(IPAddress ipAddr, String udpMsg, int udpPort) { /** WiFiUDP class for creating UDP communication */ WiFiUDP udpServer; // Start UDP client for sending packets int connOK = udpServer.begin(udpPort); if (connOK == 0) { Serial.println("UDP could not get socket"); return false; } int beginOK = udpServer.beginPacket(ipAddr, udpPort); if (beginOK == 0) { // Problem occured! udpServer.stop(); Serial.println("UDP connection failed"); return false; } int bytesSent = udpServer.print(udpMsg); if (bytesSent == udpMsg.length()) { udpServer.endPacket(); udpServer.stop(); return true; } else { Serial.println("Failed to send " + udpMsg + ", sent " + String(bytesSent) + " of " + String(udpMsg.length()) + " bytes"); udpServer.endPacket(); udpServer.stop(); return false; } } |
Nearly the same as for ESP8266, but here the mix-up between multicast and broadcast is cleaned up. udpServer.beginPacket(ipAddr, udpPort); starts the communication. Important to know: This is the same call for sending a packet to a single IP, then ipAddr is a single IP address) or to broadcast on the network, then ipAddr is a IP mask for the broadcasting.
I added some error checking here as well, which is still missing in my ESP8266 code.
UDP broadcast listener example for ESP32
Finally something that could be taken 99% from my ESP8266 code. Only difference is the spelling of the required header file. In ESP8266 the header file is WiFiUDP.h, in ESP32 the header file is WiFiUdp.h. This are the small traps you can get stuck when moving code from the ESP8266 to the ESP32.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
#include "WiFiUdp.h" /** UDP broadcast port */ static const int udpBcPort = 9997; /** WiFiUDP class for listening to UDP broadcasts */ extern WiFiUDP udpListener; void setup(void) { // Some initialization stuff // Start UDP listener udpListener.begin(udpBcPort); } void loop(void) { // here is your code that is processed in a loop // Check if broadcast arrived int udpMsgLength = udpListener.parsePacket(); if (udpMsgLength != 0) { byte udpPacket[udpMsgLength+1]; // reserve a local buffer IPAddress udpIP = udpListener.remoteIP(); // Read the received payload into the local buffer udpListener.read(udpPacket, udpMsgLength); udpPacket[udpMsgLength] = 0; udpListener.flush(); // empty UDP buffer for next packet String debugMsg = "UDP broadcast from "; debugMsg += "Sender IP: " + String(udpIP[0]) + "." + String(udpIP[1]) + "." + String(udpIP[2]) + "." + String(udpIP[3]); debugMsg += "\n Msg: " + String((char *)udpPacket); Serial.println(debugMsg); } } |






