ESP UDP Server example question

im looking at the example from HERE. i just have one question. What exactly is happening here,

    int len = Udp.read(incomingPacket, 255);
    if (len > 0)
    {
      incomingPacket[len] = 0; //? why?
    }

Heres the whole program. i understand everything except that part

#include <ESP8266WiFi.h>
#include <WiFiUdp.h>

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

WiFiUDP Udp;
unsigned int localUdpPort = 4210;  // local port to listen on
char incomingPacket[255];  // buffer for incoming packets
char  replyPacket[] = "Hi there! Got the message :-)";  // a reply string to send back


void setup()
{
  Serial.begin(115200);
  Serial.println();

  Serial.printf("Connecting to %s ", ssid);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED)
  {
    delay(500);
    Serial.print(".");
  }
  Serial.println(" connected");

  Udp.begin(localUdpPort);
  Serial.printf("Now listening at IP %s, UDP port %d\n", WiFi.localIP().toString().c_str(), localUdpPort);
}


void loop()
{
  int packetSize = Udp.parsePacket();
  if (packetSize)
  {
    // receive incoming UDP packets
    Serial.printf("Received %d bytes from %s, port %d\n", packetSize, Udp.remoteIP().toString().c_str(), Udp.remotePort());
    int len = Udp.read(incomingPacket, 255);
    if (len > 0)
    {
      incomingPacket[len] = 0;
    }
    Serial.printf("UDP packet contents: %s\n", incomingPacket);

    // send back a reply, to the IP address and port we got the packet from
    Udp.beginPacket(Udp.remoteIP(), Udp.remotePort());
    Udp.write(replyPacket);
    Udp.endPacket();
  }
}

if Udp.parsePacket(); returns the size, then wahts happening with "int len"? why is 255 passed to it?

The packet is probably sent without the terminating '\0' required to treat it as a c-string. Putting 0 on the end fixes that.

It's printing whatever was in the UDP packet to the serial port. The packet content is stored in a char array. Serial.print expects a C string, i.e. a zero terminated array of char. The mystery code ensures that it is zero terminated.

Edit: too slow!

Thankyou, okay so were adding the terminating character to incommingPacket. but why is 255 passed as an arg in this expression,

int len = Udp.read(incomingPacket, 255);

UDP packets can be huge. Arduino doesn't have much ram so when you read a packet, you need to tell the library how big the buffer is that you have set aside for it. Then it'll avoid overflowing your array if it sees a larger packet.

notsolowki:
Thankyou, okay so were adding the terminating character to incommingPacket. but why is 255 passed as an arg in this expression,

int len = Udp.read(incomingPacket, 255);

yes, it should be 254 or better sizeof(incommingPacket) - 1

Thanks everyone it makes sense to me now i think

notsolowki:
Thankyou, okay so were adding the terminating character to incommingPacket. but why is 255 passed as an arg in this expression,

int len = Udp.read(incomingPacket, 255);

As stated, it's telling the maximum number of characters to read. The source code is always the definitive answer to how functions work. That's were I usually start. Take a look and you can find out a lot of this stuff on your own. Inside 'WiFiUdp.h', you'll find the prototype for this function along with some comments:

 int read(unsigned char* buffer, size_t len) override;
  // Read up to len characters from the current packet and place them into buffer
  // Returns the number of characters read, or 0 if none are available

gfvalvo:
As stated, it's telling the maximum number of characters to read. The source code is always the definitive answer to how functions work. That's were I usually start. Take a look and you can find out a lot of this stuff on your own. Inside 'WiFiUdp.h', you'll find the prototype for this function along with some comments:

 int read(unsigned char* buffer, size_t len) override;

// Read up to len characters from the current packet and place them into buffer
  // Returns the number of characters read, or 0 if none are available

read up to len characters i think means read up to how every many bytes or the length. but i got confused when i seen 255. so 255 is just to prevent overflows? OR Just in case the packet is larger than 255, it wont read more than 255. because i'm going to need to know the length of the actual data in order to extract verification bytes from beginning and end of it.

I did read the classes it just didn't make sense to me still. but now i think i get it

If you're processing UDP packets, you probably know how big they're going to be, but you also want to defend against overflow in case some other process is sending them too. Overflow will probably crash your program or at least make it behave in unexpected ways.

This isn't restricted to UDP, whenever you're buffering data, it's a sensible practice to ensure that you don't exceed the bounds (at either end) of that buffer.

wildbill:
If you're processing UDP packets, you probably know how big they're going to be, but you also want to defend against overflow in case some other process is sending them too. Overflow will probably crash your program or at least make it behave in unexpected ways.

This isn't restricted to UDP, whenever you're buffering data, it's a sensible practice to ensure that you don't exceed the bounds (at either end) of that buffer.

Am i missing something. if i send a 32byte message will it not show up as a 32byte message?

in my UDP communications program i'm trying to make i want to verify the data being sent by the sender. I want to add the "NODE01" to the beginning and the end of the bytes im trying to send. Currently im sending like this,

if (millis() - now >= 900) {
    now = millis();
      now2 = millis();
    Udp.beginPacket(Server, ServerPort);
   Udp.write((char*)&localData, sizeof(localData));
    Udp.endPacket();
    digitalWrite(5,HIGH);
  }

How can i add that byte string to the beginning and end of the bytes being sent?

in my previous program i used somthing like this,

  if (millis() - now >= 500) {
    if (client->space() > 32 && client->canSend()) {
      client->add("NODE02", 7); //add verification1
      client->add((char *)&st, sizeof(sampleStruct));
      client->add("NODE02", 7); //add verification2
      client->send();
      Serial.println("sent");
      //client->free();
    }

EDIT: im going to try to printf it to a char array and add everything together and send that to see if it works

Okay so i tried to come up with something but it didn't work. Can you point out what i did wrong please?

sending,

 if (millis() - now >= 900) {
    now = millis();
    now2 = millis();
    char buffer[64];
    Serial.printf(buffer, "NODE01", &localData, "NODE01");
    Udp.beginPacket(Server, ServerPort);
    Udp.write((char*)&buffer, sizeof(buffer));
    Udp.endPacket();
    digitalWrite(5, HIGH);
  }

receiving,

  int packetSize = Udp.parsePacket();
  if (packetSize)
  {
    // receive incoming UDP packets

    //Serial.printf("Received %d bytes from %s, port %d\n", packetSize, Udp.remoteIP().toString().c_str(), Udp.remotePort());
    int len = Udp.read(incomingPacket, 800);
    sprintf (verifyStart, (char *)incomingPacket, 6 );
    sprintf (verifyEnd, (char *)incomingPacket + 7 + len - 14, 6 );
    Serial.println("hello");
    Serial.println(verifyStart);
    Serial.println(verifyEnd);
    digitalWrite(5, HIGH);

  }

I'd try:

const char delimiter[] = "NODE01";


  Udp.write((const uint8_t *)delimiter, sizeof(delimiter)-1);
  Udp.write((const uint8_t *)&localData, sizeof(localData));
  Udp.write((const uint8_t *)delimiter, sizeof(delimiter)-1);

LOL Serial.printf is not the command i was looking for i meant sprintf()

I'm going to need to learn how to use those delimiters. i use Robin2's serial example#5 and i have never really needed anything else. Also will this code always send buffer as 64 bytes of will the size automatically be determined up to 64 bytes?

char buffer[64];
sprintf(buffer, "NODE01", &localData, "01NODE");

I'm still having a bit of trouble with the sizeof(incomingPacket). i have successfully extracted the firt 7 bytes of the packet but now i need to get to the 7 bytes after the data structure. in theory this would be the last 7 bytes but in this case i don't know what to do?

veryfyStart i cant read just fine. but its verifyEnd im having trouble finding the right bytes. i wish len would just return the size of the data plus the extra 14 byte i send with it. i cant veryfy what the length actually is.

 int packetSize = Udp.parsePacket();
  if (packetSize)
  {
    // receive incoming UDP packets

    //Serial.printf("Received %d bytes from %s, port %d\n", packetSize, Udp.remoteIP().toString().c_str(), Udp.remotePort());
    int len = Udp.read(incomingPacket,800);
    sprintf (verifyStart, (char*)incomingPacket, 7 );
    sprintf (verifyEnd, (char *)incomingPacket + sizeof(incomingPacket) - 7, 7 ); //not working
    Serial.println("hello");
    Serial.println(verifyStart);
    Serial.println(verifyEnd);
    // Serial.printf("UDP packet contents: %s\n", incomingPacket);
    digitalWrite(5, HIGH);

the char array "buffer" i initialized as [64] but this is the sending code,

 if (millis() - now >= 900) {
    now = millis();
    now2 = millis();
    char buffer[64];
    sprintf(buffer, "NODE01", &localData, "NODE01");
    Udp.beginPacket(Server, ServerPort);
    Udp.write((char*)&buffer, sizeof(buffer));
    Udp.endPacket();
    digitalWrite(5, HIGH);
  }

At least part of the problem is that it appears you don't know how to use sprintf.

However, with the code I showed you in Reply #13, you don't need to use it at all.

I was scared that if i called UDP.write 3 times that the packet wouldn't show up as 1 single message?

it worked i must mis understood that write must be adding to a buffer itself. however im having trouble with the receiving length and the way this code is now verifyStart and veryfyEnd print the same bytes?

  int packetSize = Udp.parsePacket();
  if (packetSize)
  {
    // receive incoming UDP packets

    //Serial.printf("Received %d bytes from %s, port %d\n", packetSize, Udp.remoteIP().toString().c_str(), Udp.remotePort());
    int len = Udp.read(incomingPacket,800);
    sprintf (verifyStart, (char*)incomingPacket, 7 );
    sprintf (verifyEnd, (char *)incomingPacket + sizeof(packetSize) - 11, 7 );
    Serial.println("hello");
    Serial.println(verifyStart);
    Serial.println(verifyEnd);
    // Serial.printf("UDP packet contents: %s\n", incomingPacket);
    digitalWrite(5, HIGH);

  

  }

I chose 800 as that arg because i thought the max size char array is 1000 but im probably wrong.

EDIT: when i serial.println length it says 24. and i thought would work,

sprintf (verifyEnd, (char *)incomingPacket + 7 + len - 14, 6 );

but it does not