How can I create a UDP server with static IP?

Hi.

I have a project with a 32-bit microcontroller, of which a Shadows example is running together with Amazon Alexa.

Also in the microcontroller I have a TCP server, which allows me to connect from a mobile phone application and thus configure the hardware.

All of this works very well and they work with dynamic addresses. (DHCP)

Now I want to implement a UDP server for which I’m following the link below:

Create, Configure and Bind a UDP Socket

In this code to open the socket, the following is done:

FreeRTOS_bind( xListeningSocket, &xBindAddress, sizeof( xBindAddress ) );

But I want to open the socket with a static ip, specifically 224.0.0.252

Any suggestions how to do it?

Hello @DominusDRR,

I don’t think that it is possible to bind a socket to a non-local IP. At least not without modifying the TCP stack code. Since using a different address means that IP stack needs to allow packets with different IP address than the local one which is not a simple change.

Can you tell me why do you need a different IP address? Maybe we can find a way around this problem.

Thanks,
Aniruddha

Thanks for answering.

What happens is that I need to identify my hardware on a local network. I’m currently pinging all the IP addresses from the app. That is, if the network segment is 192.168.0.xx, I make a pin from 192.168.0.1 to 192.168.0.254.

Those addresses that respond, I try to open a socket and send a data frame, if the answer is correct, I assume that I have found a hardware in my local network (there could be more than one connected)

Obviously those IP addresses that don’t respond, or that the socket cannot be opened or that they respond to something wrong are discarded.

Those valid addresses are displayed in a list for the user to choose with which to interact.

Also, these valid addresses are saved in the application so that the next time the app is opened, it will automatically connect to the stored addresses, avoiding the scanning of the IP addresses.

This seems correct to me the first time the user installs the hardware and configures with the app

The problem is that I was informed that there are users that their routers are configured to renew their IP addresses once a month.

If this happens, the app should again perform a scan of all the IP addresses again, and this is somewhat cumbersome, since scanning all the IPs takes some time, I don’t think users are happy configuring their app and hardware once a month.

Another cumbersome solution could be to use static IP addresses, but I don’t think that’s a good idea either.

So doing some research, the suggestion I found on how to find hardware in a local network is using UDP broadcast or multicast.

This is a UDP server at Multicast IP addresses (range of 224.0.0.0-239.255.255.255).

What the application has to do is open a socket to connect to the UDP server and through that message it would obtain the dynamic IP and other possible parameters.

That way I avoid making a pin of all the IPs and everything explained above.

It is still not clear to me what you are trying to do, but note just because the IP address is being refreshed doesn’t mean it won’t be assigned the same address again. Most DHCP servers will try to give the same MAC address the same IP address each time - although that is not guaranteed.

Are you asking how to define the IP address of a remote socket you want to send data too? If so I think that is done in the sendto() function. Or are you asking how to use a broadcast packet to send data to a particular IP address? Or something else?

Hi there Fabian,

the problem you are trying to address is as old as networking itself. A TCP/UDP server whose IP address is subject to change (eg via dhcp) is a “moving target” for clients.

Normally this is addressed through protocols like DynDNS. Your envisioned solution will not work.

What I want is that only the UDP server has a constant IP, something like this:

FreeRTOS_bind( xListeningSocket, "224.0.0.252", sizeof( xBindAddress ) );

While the other services continue to work with DHCP

I think it could be with FreeRTOS_inet_addr_quick:

FreeRTOS_inet_addr_quick()

It would be something like this:

xAddress.sin_addr = FreeRTOS_inet_addr_quick( 224, 0, 0, 252);
...
FreeRTOS_bind( xListeningSocket, &xAddress, sizeof(xAddress ) );

Hello @DominusDRR, the sin_addr that you set (or don’t) in the xAddress will not be used. The socket will be bound to a port with the device’s local IP.

I agree with @RAc, generally these problems involve some kind of Name service or a server which acts as a mediator between two devices.
You may want to try out LLMNR where the target device can be queried. You’ll need to enable ipconfigUSE_LLMNR. See here for more details.

That is to say that I cannot have, for example two TCP servers with two different IP addresses in the MCU?

I will analyze your suggestion. Thanks a lot

On your local network IP addresses are routed to MAC addresses using ARP.

It’s been a while since I’ve used UDP, but it does not create a connection. You send to a UDP port, but unless the app is designed to respond, you don’t get a response. It’s a fire-and-forget protocol. As a result, you can send to another app, or listen for messages from that app. If the app knows to send a response (to a location within the UDP data), you never know it’s received it.

In UNIX/Linux you don’t connect, just send to a network tuple, or receive on a network tuple.

1 Like

That will only work if your MCU has multiple network interfaces, eg a cabled and a wireless interface. Per interface there is only one IP address, either static or dynamic.

As a real world example of what @wdtj outlined, consider SNMP. That’s a UDP based bidirectional protocol, meaning your unit acting as an SNMP agent can both receive and send SNMP packets from/to the same server. If your unit HAD two IP addresses to choose from, it wouldn’t know which address to use as the source address for outbound diagrams as inbound and outbound packets are completly independent. The SNMP server would get fairly confused if it did send out SNMP commands to the static address but received SNMP traps from the same agent from a dynamic address, or worse, varying addresses.

The TCP/IP suite isn’t designed for this kind of thing. Again, the moving target issue has been around forever, caused tens of thousands of developers to scratch their heads, and if there WAS an easy and straightforward solution, it would be well documented and easily accessible. Funnily enough, it isn’t even though it’s an ubiqutous issue. Again, the most widely used workarounds all use logical names such as DNS or LLMNR, as @kanherea suggested.

Well, taking the idea of LLMNR, and accepting that when opening a UDP socket in the microcontroller which will have as IP the one that the router has dynamically provided, what I have to do is send a data frame to address 224.0 .0.252 and it would look something like this:

xDestinationAddress.sin_addr = FreeRTOS_inet_addr( "224.0.0.252");
...
xSocket = FreeRTOS_socket( FREERTOS_AF_INET,FREERTOS_SOCK_DGRAM,/*FREERTOS_SOCK_DGRAM for UDP.*/FREERTOS_IPPROTO_UDP);
FreeRTOS_sendto(xSocket,cString,strlen( cString ),0,&xDestinationAddress,sizeof( xDestinationAddress ) );

While on the mobile phone application side, it should open the UDP socket with the address “224.0.0.252” waiting for some data from the microcontroller.

Obviously, as @wdtj mentioned, when the MCU sends the frame with data, there is no guarantee that the receiver (the app) will receive the message, so I think it should be periodically sending the data frame from the microcontroller to address “224.0.0.252”., until at some point the app manages to capture the data.

Am I right?

No, but I encourage you to give it a try and figure out for yourself why this won’t work. Instead of thinking up some pseudo code and then asking whether that’s valid code or not, the better strategy would be to make the code real code and then see what happens. You learn more that way and save turnaround time.

Hi, it seems to work, I made a simple example with the code from this thread:

Receiving Data from a Multicast Group with C#

I’m not using the microcontroller yet, use a tool that allows to open a UDP socket and send data.

Well done! :wink:

Then go ahead and try to process the data in your simulated MCU.

Bonus points: Imagine two of your units sitting in the same network. How does either of the two know which packet is directed to it when the mobile phone app serves both? After all, they both “use” the same IP address, right?

There’s more. Keep experimenting.

Thank you.
What I think is to send the dynamic IP address and the mac address, that way the application can differentiate between several devices.

No.

You should try to get a good grip of addressing, ie understand the ISO/OSI layering, the different types of addressing (MAC, IP, logical…), what those are for and which layer can see each of them.

Again, experiment and learn by doing. A lot of things will fall into place that way.

Have a merry Christmas!

1 Like

That is the magic of ‘Multi-cast’, and why a Node needs more than just the Multi-cast address.

Routers need to be able to keep track of multiple entries for IP → MAC translaslation for Multi-cast IP addresses. There is no problem with sending a single packet to a Multi-cast IP address and it getting to multiple nodes, that’s just how Multi-cast works.

Now, none of those nodes would normally reply with a source address of the Multi-cast IP, as that isn’t the nodes ‘real’ IP address.

I agree with that. Just play with the protocols and see what happens!

I have tried all possibilities that you mention. Mind you that LLMNR is using multicast.

My devices are amplifiers, and each one has a unique name, for instance: “ampli-1” up to “ampli-10”.

Now thanks to LLMNR I can ping a device as simple as this:

ping ampli-1

Or I can telnet it:

telnet ampli-2

Now I also gave them a common name, e.g. “amplifier”. When I “ping amplifier”, all devices will respond to the LLMNR lookup. The first response will be used by ping.

Note that there are two branches of FreeRTOS+TCP:

FreeRTOS-Plus-TCP IPv4 single interface (main)
FreeRTOS-Plus-TCP IPv4/IPv6/multiple interfaces

You could use the multi version, but the main version should also work for you. The main version is simpler to use.

Good luck