Verify sender of data packet ESP8266

I'm going to be receiving packets on a master ESP from 8 different nodes so i need a way to verify which node it came from and possibly that the data is intact. Should i make a variable in each packets data struct to compare to on the receiving end?

here is my sending code,

#include <ESP8266WiFi.h>
#include <ESPAsyncTCP.h>

extern "C" {
#include <osapi.h>
#include <os_type.h>
}

#include "config.h"
#define SSID "ESP-TEST"
#define PASSWORD "123456789"
#define SERVER_HOST_NAME "esp_server"
#define TCP_PORT 7050
#define DNS_PORT 53

struct sampleStruct {
  int var1;
  byte Array[20];
  float var2;
  unsigned long var3;
  unsigned long var4;
  unsigned long var5;
  unsigned long var6;
  unsigned long var7;
  unsigned long var8;
  bool var9;
};
sampleStruct st;

static os_timer_t intervalTimer;
static void replyToServer(void* arg) {
  AsyncClient* client = reinterpret_cast<AsyncClient*>(arg);

  // send reply
  if (client->space() > 32 && client->canSend()) {
    client->add((char *)&st, sizeof(sampleStruct));
    client->send();
  }
}

/* event callbacks */
static void handleData(void* arg, AsyncClient* client, void *data, size_t len) {
  Serial.printf("\n data received from %s \n", client->remoteIP().toString().c_str());
  Serial.write((uint8_t*)data, len);
  os_timer_arm(&intervalTimer, 2000, true); // schedule for reply to server at next 2s
}

void setup() {
  Serial.begin(115200);
  delay(20);
  WiFi.mode(WIFI_STA);
  WiFi.begin(SSID, PASSWORD);
  while (WiFi.status() != WL_CONNECTED) {
    Serial.print('.');
    delay(500);
  }

  AsyncClient* client = new AsyncClient;
  client->onData(&handleData, client);
  client->connect(SERVER_HOST_NAME, TCP_PORT);

  os_timer_disarm(&intervalTimer);
  os_timer_setfn(&intervalTimer, &replyToServer, client);
}

void loop() {
}

The receiving code simply uses memcpy to move the data to the struct.

#include <ESP8266WiFi.h>
#include <ESPAsyncTCP.h>
#include <DNSServer.h>
#include <vector>
#include "config.h"

#define SSID "ESP-TEST"
#define PASSWORD "123456789"
#define SERVER_HOST_NAME "esp_server"
#define TCP_PORT 7050
#define DNS_PORT 53

static DNSServer DNS;
struct sampleStruct {
  int var1 = 99;
  //byte Array[];
  float var2 = 0;
  unsigned long var3 = 0;
  unsigned long var4 = 0;
  unsigned long var5 = 0;
  unsigned long var6 = 0;
  unsigned long var7 = 0;
  unsigned long var8 = 0;
  bool var9 = 0;
};
sampleStruct st;

static std::vector<AsyncClient*> clients; // a list to hold all clients

static void handleData(void* arg, AsyncClient* client, void *data, size_t len) {
  Serial.printf("\n data received from client %s \n", client->remoteIP().toString().c_str());
  memcpy(&st, data, sizeof(data));
  Serial.write((char*)&data, sizeof(data));

  // reply to client
  if (client->space() > 32 && client->canSend()) {
    char reply[32];
    sprintf(reply, "this is from %s", SERVER_HOST_NAME);
    client->add(reply, strlen(reply));
    client->send();
  }
}

/* server events */
static void handleNewClient(void* arg, AsyncClient* client) {
  Serial.printf("\n new client has been connected to server, ip: %s", client->remoteIP().toString().c_str());

  // add to list
  clients.push_back(client);

  // register events
  client->onData(&handleData, NULL);
}

void setup() {
  Serial.begin(115200);
  delay(20);
  Serial.println("server");
  // create access point
  while (!WiFi.softAP(SSID, PASSWORD, 6, false, 15)) {
    delay(500);
  }

  // start dns server
  if (!DNS.start(DNS_PORT, SERVER_HOST_NAME, WiFi.softAPIP()))
    Serial.printf("\n failed to start dns service \n");

  AsyncServer* server = new AsyncServer(TCP_PORT); // start listening on tcp port 7050
  server->onClient(&handleNewClient, server);
  server->begin();
}

void loop() {
  DNS.processNextRequest();
}

Right now the code is very basic and built from ESPAsyncTCP Client/Server examples.

I'm having trouble finding information for ESP8266 about ACK. I'm using ESP8266AsyncTCP library it don't have any mention on what the classes are. Is ACK automatically enabled? will the be enough to verify integrity of the data being received? What would i ideal/simple method be to verify the received data so i don't update a struct with corrupt data? How could i attach a byte to the beginning and end of the data being sent and remove them after i receive the data and the two extra bytes match?

Okay i have come up with some code that adds VERIFY to the beginning and VERIFI at the end of the bytes,I think i should convert those bytes to strings? However i need help figuring out how to compare the two strings. I could do this without help if i used just a single char. would a single character be just as good as using the whole string? should i use the string datatype to store the string?

sending code,

#include <ESP8266WiFi.h>
#include <ESPAsyncTCP.h>

extern "C" {
#include <osapi.h>
#include <os_type.h>
}

#include "config.h"
#define SSID "ESP-TEST"
#define PASSWORD "123456789"
#define SERVER_HOST_NAME "esp_server"
#define TCP_PORT 7050
#define DNS_PORT 53

struct sampleStruct {
  int var1 = 253;
  //byte Array[20];
  float var2 =5.5;
  unsigned long var3 = 999;
  unsigned long var4 =1;
  unsigned long var5=9999;
  unsigned long var6=7777;
  unsigned long var7=6666;
  unsigned long var8=5555;
 // bool var9;
};
sampleStruct st;

static os_timer_t intervalTimer;

static void replyToServer(void* arg) {
  AsyncClient* client = reinterpret_cast<AsyncClient*>(arg);
  // send reply
  if (client->space() > 32 && client->canSend()) {
   client->add("VERIFY",7); //add verification1
   client->add((char *)&st, sizeof(sampleStruct));
      client->add("VERIFI",7);//add verification2
    client->send();
    Serial.println("sent");
  }
}

/* event callbacks */
static void handleData(void* arg, AsyncClient* client, void *data, size_t len) {
  Serial.printf("\n data received from %s \n", client->remoteIP().toString().c_str());
  Serial.write((uint8_t*)data, len);
  os_timer_arm(&intervalTimer, 2000, true); // schedule for reply to server at next 2s
}
void onConnect(void* arg, AsyncClient* client) {
  Serial.printf("\n client has been connected to %s on port %d \n", SERVER_HOST_NAME, TCP_PORT);
  replyToServer(client);
}
void setup() {
  Serial.begin(115200);
  delay(20);
  WiFi.mode(WIFI_STA);
  WiFi.begin(SSID, PASSWORD);
  while (WiFi.status() != WL_CONNECTED) {
    Serial.print('.');
    delay(500);
  }

  AsyncClient* client = new AsyncClient;
  client->onData(&handleData, client);
    client->onConnect(&onConnect, client);
  client->connect(SERVER_HOST_NAME, TCP_PORT);

  os_timer_disarm(&intervalTimer);
  os_timer_setfn(&intervalTimer, &replyToServer, client);
}

void loop() {
  
}

receiving code,

#include <ESP8266WiFi.h>
#include <ESPAsyncTCP.h>
#include <DNSServer.h>
#include <vector>
#include "config.h"

#define SSID "ESP-TEST"
#define PASSWORD "123456789"
#define SERVER_HOST_NAME "esp_server"
#define TCP_PORT 7050
#define DNS_PORT 53

static DNSServer DNS;
struct sampleStruct {
  int var1 = 99;
  //byte Array[];
  float var2 = 0;
  unsigned long var3 = 0;
  unsigned long var4 = 0;
  unsigned long var5 = 888;
  unsigned long var6 = 0;
  unsigned long var7 = 0;
  unsigned long var8 = 0;
  //  bool var9 = 0;
};
sampleStruct st;

static std::vector<AsyncClient*> clients; // a list to hold all clients

static void handleData(void* arg, AsyncClient* client, void *data, size_t len) {

  Serial.printf("\n data received from client %s \n", client->remoteIP().toString().c_str());
  memcpy(&st, data + 7, sizeof(sampleStruct));
  Serial.write((const char *)data, 7);
  Serial.println("");
  Serial.println(st.var1);
  Serial.println(st.var2);
  Serial.println(st.var3);
  Serial.println(st.var4);
  Serial.println(st.var5);
  Serial.println(st.var6);
  Serial.println(st.var7);
  Serial.println(st.var8);
  //Serial.println(st.var9);
  Serial.write((const char *)data + 7 + sizeof(sampleStruct), 7);


  // reply to client
  if (client->space() > 32 && client->canSend()) {
    char reply[32];
    sprintf(reply, "this is from %s", SERVER_HOST_NAME);
    client->add(reply, strlen(reply));
    client->send();
  }
}

/* server events */
static void handleNewClient(void* arg, AsyncClient* client) {
  Serial.printf("\n new client has been connected to server, ip: %s", client->remoteIP().toString().c_str());

  // add to list
  clients.push_back(client);

  // register events
  client->onData(&handleData, NULL);
}

void setup() {
  Serial.begin(115200);
  delay(20);
  Serial.println("server");
  // create access point
  while (!WiFi.softAP(SSID, PASSWORD, 6, false, 15)) {
    delay(500);
  }

  // start dns server
  if (!DNS.start(DNS_PORT, SERVER_HOST_NAME, WiFi.softAPIP()))
    Serial.printf("\n failed to start dns service \n");

  AsyncServer* server = new AsyncServer(TCP_PORT); // start listening on tcp port 7050
  server->onClient(&handleNewClient, server);
  server->begin();
}

void loop() {
  DNS.processNextRequest();
}

Serial output is,

VERIFY
253
5.50
999
1
9999
7777
6666
5555
VERIFI

This is what i came up with to verify the sender. Please let me know if you see any problems. Is this a bad idea?

Receive function,

char verifyStart[7];
char verifyEnd[7];
static void handleData(void* arg, AsyncClient* client, void *data, size_t len) {
  sprintf (verifyStart,(char *)data, 6 );
  sprintf (verifyEnd,(char *)data + 7 + len - 14, 6 );
  if (strcmp(verifyStart, "NODE01") == 0) {
    if (strcmp(verifyEnd, "NODE01") == 0) {
      //Update Node01 struct
    }
  }
    if (strcmp(verifyStart, "NODE02") == 0) {
    if (strcmp(verifyEnd, "NODE02") == 0) {
      //Update Node02 struct
    }
  }
  //etc
  Serial.printf("\n data received from client %s \n", client->remoteIP().toString().c_str());
  //  memcpy(&st, data + 7, sizeof(sampleStruct));

  if (client->space() > 32 && client->canSend()) {
    char reply[32];
    sprintf(reply, "this is from %s", SERVER_HOST_NAME);
    client->add(reply, strlen(reply));
    client->send();
  }
}

Send function,

static void replyToServer(void* arg) {
  AsyncClient* client = reinterpret_cast<AsyncClient*>(arg);
  // send reply
  if (client->space() > 32 && client->canSend()) {
   client->add("NODE01",7); //add verification1
   client->add((char *)&st, sizeof(sampleStruct));
      client->add("NODE01",7);//add verification2
    client->send();
    Serial.println("sent");
  }
}

This is the best i could come up with, with what little knowledge i have