Can you increase the size of a UDP packet?

Using a photon/argon…

On the photon, it looks like I am limited to a 512 byte UDP packet. Is this a UDP limitation? Or can I increase the size of this packet?

I am using udp.write(String);

If this requires using udp.write(const uint8_t buffer, int size) I could use some help translating a String to the uint8_t array (I can’t seem to figure that out). But I am still not sure that would work to get >512 bytes.

Thanks!

My mistake… the extra bytes appear to be header/metadata I was seeing with Wireshark.

So it looks like my data payload is limited to 512, and I tested that with:

for (int i = 0; i<1024;i++){ udp.write("X");}

This might help
https://docs.particle.io/reference/device-os/firmware/photon/#tochararray-


(Update: The following section missed the point that upd.write() calls need to be enclosed with udp.beginPacket() and udp.endPacket() to actually send the data - hence I’ve hidden it)

hidden suggestions But you don't even need to *copy* the string, you can just *take* the string as is and use this ```cpp const uint8_t* buf = (const uint8_t*)yourString.c_str(); int len = yourString.length(); udp.write(buf; len % 512); // first packet shorter to have the rest exactly 512 for (int i = len % 512; i < yourString.length(); i += 512) { udp.write(&buf[i], 512); ``` *(this is not tested, so you may need some type casts here or there ;-) )*

Or you use the return value of udp.write() like this

  const uint8_t* buf = (const uint8_t*)yourString.c_str();
  int sent = 0;
  while(sent < strlen((const char*)buf)) 
    sent += udp.write(&buf[sent], strlen((const char*)&buf[sent]));  // try sending rest of string and accumulate the number of actually sent bytes

and many more possible approaches :wink:

But be aware UDP does not guarantee that all packets are actually delivered.

Thank you once again. But why would that work, when I tried calling udp.write() in a loop 1024 times? I also tried to split my string up into smaller portions and write multiple times, in writes < 512.

Oh… is this because the udp buffer is filling up, and I am trying to write to it too quickly?

And yes, I am aware that not all packets will arrive. The idea here is to have a remote sensor broadcasting its live data to the subnet. That part is working fine.

But what I thought would be a good idea would be to have the sensor buffer a good amount of data, and send that in the same packet as the latest data (say, 1024 samples). I am sending this out as formatted JSON, so the packet would be a couple kilobytes.

When using UDP only in your self controlled environment I’d suggest you stick with a binary format rather than inflating the data with not extra value.
Keeps things shorter and also faster.

And what were the results of that?

I tested with this:
for (int i = 0; i<1024;i++){ udp.write("X");}

And my packet data is still cut off at 512 bytes.

I also just tried small delays in between those individual writes (10us, 100us, 1ms) and still cut off at 512.

Are you running SYSTEM_THREAD(ENABLED) - if not, try that.
You can also try adding a Particle.process() in your loop to force the network stack to engage (although I’d think that shouldn’t be required).

BTW, I just stumbled over this (again :blush:)
https://docs.particle.io/reference/device-os/firmware/photon/#write--5


So my proposed “solutions” above won’t work either.

Alternatively you can use udp.sendPacket() to send unbuffered or use udp.setBuffer() to donate a bigger buffer.

1 Like

With SYSTEM_THREAD(ENABLED), I don’t see any packets at all. IT’s breathing cyan, but wireshark sees nothing. If I recompile witih that commented out, I get packets.

I’ll see if I can set the buffer. Maybe that’s it.

Have you made sure to adhere to this?

1 Like

Dammit!!! Thank you! I read through all that last week, and of course didn’t think to refresh now that I’m knee deep.

The buffer worked. I guess you can only fill the buffer once per packet. Makes sense, I suppose… you can’t send a packet in pieces from app code, defeats the purpose, no?

1 Like

OK. So now…

I woke up this morning and there are no UDP packets. I suspect that the device disconnected from WiFi at some point.

How can I detect this and reset the udp with another udp.begin()?

udo.write() returns the bytes sent to the buffer; so that doesn’t tell me what was sent out.

Do I need to poll and catch the network at a point when it’s down to make this work? do I just reset udp on every loop (not a problem, since this one is just sending data one way).

Or do I use udp.sendPacket(), which sends it unbuffered, and hopefully the return count will be zero when this problem occurs?

I’ll try this.

The docs for udp.begin() do show that too :wink:

https://docs.particle.io/reference/device-os/firmware/photon/#begin--7

1 Like

I saw that, and I started testing.

I deliberately called WiFi.disconnect() in order to kill the connection for a few seconds… then reconnected and ran the startPacket/write/endPacket. But this was successful (packet sent). Note that the sendPacket() method also worked, without returning a zero, so I was unable to test if that fixed the issue.

I then repeated with WiFi.Off/On. I watched the device reconnect.

Is there some UDP timeout that kills the connection?

So I’m not sure I understand how this entire thing works.

UDP is connectionless, so no.

But you may run out of sockets when not calling udp.stop() before requesting.
Consequently I’m not sure whether that example in the docs is “complete”, but for further details I’d defer to @rickkas7 who knows more about the actual UDP stack.

Looking at other docs, I found some references to “UDP timeout”. But neither my mac or my PC seem to have this value listed in their configurations.

I’ll include the code and maybe program in a long, long wifi downtime to test it.

I was also wondering about calling udp.stop(), so I’ll put that in there ahead of the begin in that loop.

Since the UDP object inherits from the Stream class there will be individual functions that have their own timeout but that’s only confined to that call and not to a (non-existent) UDP connection.

There is no timeout in UDP itself. You should use SYSTEM_THREAD(ENABLED) or SYSTEM_MODE(SEMI_AUTOMATIC) and monitor WiFi.ready() and when it goes from false to true call UDP.begin() to start the listener. When the network goes away, either because you called WiFi.disconnect() or the access point went away, the listeners are removed. It won’t hurt to call UDP.stop() before calling UDP.begin()but it’s not necessary.

2 Likes

Thank you both, I have incorporated those changes.

However, I tried to test it by explicitly calling WiFi.disconnect/connect and then tried WiF.Off/On, and waiting as much as 10s with the connection down.

That did not disrupt the connection, and I did not need to re-call udp.begin().

I don’t disbelieve you guys, I am just trying to wrap my head around it. :slight_smile: