Sending UDP broadcast

Hi all, I am using Windows 10, ESP32S, and AsyncUDP library.

I have a project where I need to communicate with a server app using UDP for discovery and then with TP for everything else. I am stuck in the discovery phase.

My intention is to send a UDP broadcast that the server will receive and answer. The reply contains initialization information for to my client so that, among other things, it can switch over to TCP. I have not done UDP/TCP programming on the Arduino platform before, so I thought I would start by using one of the provided examples: AsyncUDPClient.ino. I made the following changes:

Used my own WiFi credentials.
Removed many lines from the receive packet code.
Changed the port # from 1234 to what the server is using 6309 (for UDP). Code follows.

#include "WiFi.h"
#include "AsyncUDP.h"

const char * ssid = "...";
const char * password = "...";

AsyncUDP udp;

void setup()
{
    Serial.begin(115200);
    WiFi.mode(WIFI_STA);
    WiFi.begin(ssid, password);
    if (WiFi.waitForConnectResult() != WL_CONNECTED) {
        Serial.println("WiFi Failed");
        while(1) {
            delay(1000);
        }
    }

    //The server is receiving on port 6309
    //if(udp.listen(6309)) {
    if(udp.connect(IPAddress(255,255,255,255), 6309)) {
        Serial.println("UDP connected");
        udp.onPacket([](AsyncUDPPacket packet) {
            Serial.print(", From: ");
            Serial.print(packet.remoteIP());
            Serial.print(", Data: ");
            Serial.write(packet.data(), packet.length());
            Serial.println();
            //reply to the client
            packet.printf("Got %u bytes of data", packet.length());
        });
        //Send unicast
        udp.print("Hello Server!");
    }
}

void loop()
{
    delay(1000);
    //Send broadcast on port 1234
    udp.broadcastTo("Server, are you there?", 6309);
}
type or paste code here

Documentation is scarce, so I assumed that the two port references (1234 originally), now 6309 refer to the port the server is listening to. With the server running, and this sketch running, the server does not receive anything. Obviously, the message that is sent in the sketch is not a valid request for the server, but in that case, the server just displays whatever it receives.

After some research, I found some people are using the Listen method, instead of the connect method, but no reason is given. I tried this and still it did not work. Thinking that maybe one of the port references was for the local sending port, I modified these two references to test various combinations, but still the server was not receiving anything. I went as far as changing the broadcast address (255,255,255,255) to the server’s ip, but still no success. Much of the information that I found is different than what I am using, and since only code snippets are provided, I can only guess that others are using a different library, especially when the networking hardware is an Ethernet shield or the ESP 8266.

Why isn’t the sample sketch working? What am I missing? Any orientation is welcomed. Thank you for your time and assistance. Saga

How are the PC and ESP linked together, are they both using Wifi to a common AP?
Does the PC have ethernet as well as Wifi?
Can you post the output of using a command prompt to run ipconfig?
Is there a Firewall on the PC, can you turn it off for testing?
Can we see the code on the PC, especially the section processing the UDP?
Can you obtain the local IP address on the ESP?
Can you ping the ESP from the PC?

Hello, thank you for the follow up. I needed some time to fully answer your questions.

*How are the PC and ESP linked together, are they both using Wifi to a common AP?

Yes, common AP, but not both WiFi. I have an AP connected to the Ethernet network. The PC is on Ethernet and the ESP32 is on the Wifi. I have a second computer, a laptop, also on WiFi. The ESP32 is connected to the Ethernet desktop which is the Arduino dev station.

DevSetup.png

*Does the PC have ethernet as well as Wifi?

No, Ethernet only.

*Can you post the output of using a command prompt to run ipconfig?

Sure, this is the output of the Arduino Dev station:

Ethernet adapter Ethernet:
Connection-specific DNS Suffix . : hsd1.il.comcast.net
IPv6 Address. . . . . . . . . . . : 2601:243:180:73d0::11b
IPv6 Address. . . . . . . . . . . : 2601:243:180:73d0:3c20:c30e:feed:eb19
Temporary IPv6 Address. . . . . . : 2601:243:180:73d0:2414:91d:a41a:9901
Link-local IPv6 Address . . . . . : fe80::3c20:c30e:feed:eb19%6
IPv4 Address. . . . . . . . . . . : 10.0.0.5
Subnet Mask . . . . . . . . . . . : 255.255.255.0
Default Gateway . . . . . . . . . : fe80::5ee3:eff:fec7:390b%6
10.0.0.1

*Is there a Firewall on the PC, can you turn it off for testing?

Turned firewall off at the desktop Arduino dev station. Server app is now receiving UDP messages from the ESP32. Turned firewall back on. Server continues to receive UDP messages from ESP32. I will restart the dev station to verify that the server continues to receive UDP messages.

OK, restarted computer. Restarted server app, continues to receive UDP messages. As a second test, I disconnected the ESP32 from the Dev station and connected it to the laptop. After a few seconds, the server app on the Dev station started to receive the UDP messages.

*Can we see the code on the PC, especially the section processing the UDP?

Sure, C# code follows. This is the callback function that fires when UDP message is received. Take into consideration that currently, since I am sending it nonsense text, the only code getting executed is the default block of the switch statement:

void recv(IAsyncResult res)
{
IPEndPoint RemoteIP = new IPEndPoint(IPAddress.Any, 0);
byte rxData = uClient.EndReceive(res, ref RemoteIP);
string sTxBuf = “”;

sData = Encoding.ASCII.GetString(rxData);

//Process only if data received is longer than 3 chars.
if (sData.Length > 2)
{
switch (sData.Substring(0, 3).ToUpper())
{
case “[[A”:
//
//Command: Client is requesting ip address and file number.
//
// 012345678901234
// [[a123456123456

LogMessage("*" + sData);

//I need to send back the ip address and file number or error.

//[[A command length must be exactly 15 chars.
if (sData.Length == 15)
{
//Create an entry in the client list for this job. First, check
//if the mac address has been use. If so then just return file number
int iClientFileNum = GetExistingFileNum(sData.Substring(3).ToUpper());

//sServerIP contain this server’s ip address.
sTxBuf = sServerIP + “;”;

if (iClientFileNum > 0)
//MAC address found, just use existing file number.
sTxBuf += iClientFileNum.ToString();
else
{
LogMessage(“MAC address not found, new entry”);
//MAC address not found, so get a new file number.
iClientFileNum = GetNextFileNum();

sTxBuf += iClientFileNum.ToString();

//Create an entry in the client jobs list.
//Save: File number
// Job file name
// Client MAC address
PrintClients.Add(iClientFileNum, new
ClientInfo(CreateFileName(iClientFileNum), 0,
sData.Substring(3).ToUpper()));

}

}
else
{
//Bad command length.
LogMessage(“Bad format for Address Request command.”);

sTxBuf = “*Bad format for Address Request command.”;
}

//Send back the ip and file number. Prefix it with [[A.
//If bad A command then send back message.
var byReply = Encoding.ASCII.GetBytes("[[A" + sTxBuf);
//uClient.Send(byReply, byReply.Length, RemoteIP.Address.ToString(), uPORT);
uClient.Send(byReply, byReply.Length, RemoteIP);

LogMessage("ip: " + RemoteIP.Address.ToString() + " Port: " +
RemoteIP.Port.ToString());

break;
default:
//Something else, just display.
LogMessage(sData);

break;
}
}

//Get it ready for the next receive.
uClient.BeginReceive(new AsyncCallback(recv), null);

}

*Can you obtain the local IP address on the ESP?

Yes, used Serial.printñn(WiFi.localIP());

This works fine.

FYI: ESP ip is 10.0.0.179

*Can you ping the ESP from the PC?

Yes, no problem I can ping it from the dev station and from the laptop.

OK, so the key was the firewall. I don’t know why the server started receiving after I disabled the firewall OFF, then continued receiving the UPD messages after I re-enabled it again.

I did notice a pattern. If the UDP client ran on the same PC as the server, all was fine. It was only when the client, either a Win app or the ESP32 sketch, ran on a different PC then this issue presented itself. It looks like it was a firewall permissions issue. In my head, I keep thinking that I needed to configure the firewall to get the server to receive UDP messages from other computers (laptop/ESP32).

Although the problem is solved, I have no idea how it was solved. Any further remarks? Thank you for your help and ideas to troubleshooting this issue, much appreciated!

The reason for so many questions to start with is that I have no idea of how much experience you have with networking and how much understanding. For example, it is not uncommon for find someone using a laptop with both Ethernet and Wifi and not realising they have 2 ip addresses etc.

I can’t explain why the firewall blocked things then allowed them after it had been turned off and back on - unless it has some sort of learning process to create automatic rules.

One thing you may want to look at in future is Wireshark, that would allow you to see the packets on the Ethernet destined for or emanating from the PC including ip addresses, contents etc.

Good luck with the rest of your project.

Thanks! No problem with the questions. In fact, these gave me a sequence of steps to follow in the troubleshooting process. I’ve had issues with the firewall, nothing I couldn’t resolve by allowing the app’s data through, but I’ll admit that I did not think it would be the firewall again. I was 100% focused on the code. Lack of understanding of the Async UDP didn’t help ether.

I’ve heard of Wireshark, and I believe I used it some way back when coding network drivers, but I haven’t used this handy tool in a long while. I’ll have to revisit it. Thanks for the suggestion. Regards, Saga

Of note: The firewall problem came back the next day when I powered up the dev station and began testing. What I finally did was, in the Firewall's Advanced Settings, I created a rule, specified the ports that the app uses, specified UDP and allowed their use.

I am hoping that this permanently resolves the issue :grinning:

FYI for posterity. Saga

Thanks for posting the update. Having a clear positive conclusion to a thread like this can help others in the future should they be in a similar position.