HTTP vs MQTT Protocols for Large Packets

Hello Everyone,

I am trying to send data very fast in large packets (1000 to 1500 bytes) to a server and currently am using HTTP. The problem is that during the sending procedure, the data coming from the transmitter is being lost and I am losing large amounts of data since I am sending data at a rate of 0.014 seconds. The server has to receive the request and connect and then disconnect which takes around 3 or 4 seconds, so I am losing over 200+ data points. Can MQTT help me in this case? Any guidance is appreciated.

Code is below:

#include <esp_now.h>
#include <WiFi.h>

#define TINY_GSM_MODEM_SIM7000
#define SerialMon Serial
#define SerialAT Serial1
#define TINY_GSM_RX_BUFFER 1024
#define DUMP_AT_COMMANDS
#define TINY_GSM_DEBUG SerialMon
#define GSM_AUTOBAUD_MIN 9600
#define GSM_AUTOBAUD_MAX 115200
#define TINY_GSM_USE_GPRS true
#define TINY_GSM_USE_WIFI false
#define GSM_PIN ""

const char apn[]      =  Hidden
const char gprsUser[] = "";
const char gprsPass[] = "";

const char server[]   = Hidden
const int  port       = 80; 


#include <TinyGsmClient.h>
#include <ArduinoHttpClient.h>

#ifdef DUMP_AT_COMMANDS
#include <StreamDebugger.h>
StreamDebugger debugger(SerialAT, SerialMon);
TinyGsm        modem(debugger);
#else
TinyGsm        modem(SerialAT);
#endif

#define UART_BAUD   115200
#define PIN_DTR     25
#define PIN_TX      27
#define PIN_RX      26
#define PWR_PIN     4

TinyGsmClient client(modem);
HttpClient    http(client, server, port);
int counter, lastIndex, numberOfPieces = 24;
String pieces[24], input;
float value_data[8] = {0.0};
int count = 0;
int url_Check = 0;

//Function Declaration
void updateData();
void initGSM();
void connectAPN();

//String data1 , data2 , data3 , data4, data5, data6, data7;
String data_Post = "";
char resource[2048];
typedef struct struct_message {

  char depth1[10];
  char depth2[10];
  char depth3[10];
  char depth4[10];
  char accel_x[10];
  char accel_y[10];
  char accel_z[10];
  char TTime[40];
  char Temp[10];

} struct_message;


struct_message myData;
void OnDataRecv(const uint8_t * mac, const uint8_t *incomingData, int len) {
  memcpy(&myData, incomingData, sizeof(myData));
  /*
    Serial.print("\n Bytes received: ");
    Serial.println(len);
    Serial.print("\n Depth_1: ");
    Serial.println(myData.depth1);
    Serial.print("\n Depth_2: ");
    Serial.println(myData.depth2);
    Serial.print("\n Depth_3: ");
    Serial.println(myData.depth3);
    Serial.print("\n Depth_4: ");
    Serial.println(myData.depth4);
    Serial.print("\n X-Accel: ");
    Serial.println(myData.accel_x);
    Serial.print("\n Y-Accel: ");
    Serial.println(myData.accel_y);
    Serial.print("\n Z-Accel: ");
    Serial.println(myData.accel_z);

  */
  //convert to Float
  value_data[0] = String(myData.depth1).toFloat();
  value_data[1] = String(myData.depth2).toFloat();
  value_data[2] = String(myData.depth3).toFloat();
  value_data[3] = String(myData.depth4).toFloat();
  value_data[4] = String(myData.accel_x).toFloat();
  value_data[5] = String(myData.accel_y).toFloat();
  value_data[6] = String(myData.accel_z).toFloat();
  value_data[7] = String(myData.Temp).toFloat();

  
  /*
    &D1= depth1 sensor
    &D2= depthe2 sensor
    &D3= deppth3 sensor
    &D4= depthe4 sensor
    &X= X-acceleration
    &Y= Y-acceleration
    &Z= Z-acceleration
    &Te= Temperature
    &T= Time
   */
  if (value_data[0] == 0 && value_data[1] == 0 && value_data[2] == 0 && value_data[3] == 0 &&  value_data[7] == 0) // If depth1,2,3,4 & Temp is equal to zero. It means we are only sending Acceleration & time
  {
    if (url_Check == 0)
    {
      data_Post += "/update4.php?data=1";

    }

    data_Post += "&X=" + String(value_data[4], 4 ) + "&Y=" + String(value_data[5], 4) + "&Z=" + String(value_data[6], 4) + "&T=" + String(myData.TTime);
    count++;
    url_Check = 1;
    if (count == 20) //change the packet size
    {
      Serial.println(data_Post);
       updateData();
      //delay(5000);
      count = 0;
      data_Post = "";
      url_Check = 0;

    }

  }
  else  // send complete packet 
  {
     data_Post += "/update4.php?data=2";
     data_Post += "&D1=" + String(value_data[0], 4 ) + "&D2=" + String(value_data[1], 4) + "&D3=" + String(value_data[2], 4) + "&D4=" + String(value_data[3], 4);
     data_Post += "&X=" + String(value_data[4], 4 ) + "&Y=" + String(value_data[5], 4) + "&Z=" + String(value_data[6], 4) + "&Te=" + String(value_data[7], 4);
     data_Post += "&T=" + String(myData.TTime); 
     Serial.println(data_Post);
    updateData();

  }


}


//This Setup code is executed once then moves to void loop

void setup() {
  SerialMon.begin(115200);
  delay(10);
  initGSM();
  delay(2000);
  connectAPN();
  delay(2000);
  WiFi.mode(WIFI_STA);
  if (esp_now_init() != ESP_OK) {
    Serial.println("Error initializing ESP-NOW");
    return;
  }
  else {
    Serial.println("ESP-NOW initialized Sucessfully");
  }
  esp_now_register_recv_cb(OnDataRecv);
}

void loop() {
  
}


//Intilization and Setup is everything above this comment Line


//The board is only intended to perform specific tasks once during the setup phase and
//then wait for external events or interrupts to trigger new actions or behaviors. In this case,
//the loop() function may be left blank because the board does not need to do anything continuously.
//You have to have a loop() function, but it doesn't have to have anything in it.
//So put everything in setup(), and have an empty loop().


void updateData() {

  if (modem.isGprsConnected()) {
     char resource[2048];


    // SerialMon.print(F("Performing HTTP GET request... "));



    data_Post.toCharArray(resource , data_Post.length() + 1);
    Serial.println(resource);
    Serial.println("---------------END PACKET------");
    Serial.println("-----Sending Data starts----");
    int err = http.get(resource);
    if (err != 0) {
      SerialMon.println(F("failed to connect"));
      delay(10000);
      return;
    }
    Serial.println("----sending data ends----");
    //  int status_code = http.responseStatusCode();
    //      SerialMon.print(F("Response status code: "));
    //      SerialMon.println(status_code);
    //      if (!status_code) {
    //        //delay(10000);
    //       // return;
    //      }
    //      SerialMon.println(F("Response Headers:"));
    //      while (http.headerAvailable()) {
    //        String headerName  = http.readHeaderName();
    //        String headerValue = http.readHeaderValue();
    //        SerialMon.println("    " + headerName + " : " + headerValue);
    //      }
    //      int length = http.contentLength();
    //      if (length >= 0) {
    //        SerialMon.print(F("Content length is: "));
    //        SerialMon.println(length);
    //      }
    //      if (http.isResponseChunked()) {
    //        SerialMon.println(F("The response is chunked"));
    //    }
    String body = http.responseBody();
    //  SerialMon.println(F("Response:"));
    //   SerialMon.println(body);
    // http.stop();
    //  http.connectionKeepAlive();
    //      SerialMon.println(F("Server disconnected"));


  }
  else {
    
    if (!modem.gprsConnect(apn, gprsUser, gprsPass))
    {
      Serial.println("---GPRS not connected!----");
      Serial.println("---Re-initit GSM/GPRS---");
      initGSM();
      connectAPN();

    }
    else
    {
      Serial.println("---GPRS is connected!---");
    }

  }


}



void initGSM() {

  Serial.println("-------InitGSM starts-----");

  pinMode(PWR_PIN, OUTPUT);
  digitalWrite(PWR_PIN, HIGH);
  delay(300);
  digitalWrite(PWR_PIN, LOW);

  SerialAT.begin(UART_BAUD, SERIAL_8N1, PIN_RX, PIN_TX);
  Serial.println("Initializing modem...");
  //  if (!modem.restart()) {
  //    Serial.println("Failed (modem.restart()) to restart modem, attempting to continue without restarting");
  //  }
  Serial.println("Initializing modem...");
  if (!modem.init()) {
    Serial.println("Failed  (modem.init()) to restart modem, attempting to continue without restarting");
  }

  String name = modem.getModemName();
  //delay(500);
  Serial.println("Modem Name: " + name);

  String modemInfo = modem.getModemInfo();
  //delay(500);
  Serial.println("Modem Info: " + modemInfo);
  if ( GSM_PIN && modem.getSimStatus() != 3 ) {
    modem.simUnlock(GSM_PIN);
  }
  modem.sendAT("+CFUN=0 ");
  if (modem.waitResponse(10000L) != 1) {
    DBG(" +CFUN=0  false ");
  }
  //delay(200);
  String res;
  res = modem.setNetworkMode(2);
  if (res != "1") {
    DBG("setNetworkMode  false ");
    return ;
  }
  //delay(200);
  res = modem.setPreferredMode(1);
  if (res != "1") {
    DBG("setPreferredMode  false ");
    return ;
  }
  //delay(400);
  modem.sendAT("+CFUN=1 ");
  if (modem.waitResponse(10000L) != 1) {
    DBG(" +CFUN=1  false ");
  }
  //delay(200);

  SerialAT.println("AT+CGDCONT?");
  delay(50);
  if (SerialAT.available()) {
    input = SerialAT.readString();
    for (int i = 0; i < input.length(); i++) {
      if (input.substring(i, i + 1) == "\n") {
        pieces[counter] = input.substring(lastIndex, i);
        lastIndex = i + 1;
        counter++;
      }
      if (i == input.length() - 1) {
        pieces[counter] = input.substring(lastIndex, i);
      }
    }
    input = "";
    counter = 0;
    lastIndex = 0;

    for ( int y = 0; y < numberOfPieces; y++) {
      for ( int x = 0; x < pieces[y].length(); x++) {
        char c = pieces[y][x];  //gets one byte from buffer
        if (c == ',') {
          if (input.indexOf(": ") >= 0) {
            String data = input.substring((input.indexOf(": ") + 1));
            if ( data.toInt() > 0 && data.toInt() < 25) {
              modem.sendAT("+CGDCONT=" + String(data.toInt()) + ",\"IP\",\"" + String(apn) + "\",\"0.0.0.0\",0,0,0,0");
            }
            input = "";
            break;
          }
          // Reset for reuse
          input = "";
        } else {
          input += c;
        }
      }
    }
  } else {
    Serial.println("Failed to get PDP!");
  }

  Serial.println("\n\n\nWaiting for network...");
  if (!modem.waitForNetwork()) {
    //delay(10000);
    return;
  }

  if (modem.isNetworkConnected()) {
    Serial.println("Network connected");
  }

  Serial.println("\n---Starting GPRS TEST---\n");
  Serial.println("Connecting to: " + String(apn));
  if (!modem.gprsConnect(apn, gprsUser, gprsPass)) {
    //delay(10000);
    return;
  }

  Serial.print("GPRS status: ");
  if (modem.isGprsConnected()) {
    Serial.println("connected");
  } else {
    Serial.println("not connected");
  }

  Serial.println("--------Init GSM ends-------");
}


void connectAPN() {
  Serial.print("Connecting to APN: ");
  Serial.print(apn);
  if (!modem.gprsConnect(apn, gprsUser, gprsPass)) {
    Serial.println(" fail");
  }
  else {
    Serial.println(" OK");
  }
}

MQTT would not close the connection so you would save there.

The usual pubsubclient library has a maximum message size, including header of 256 bytes by default, so you would need to change MQTT_MAX_PACKET_SIZE in PubSubClient.h or call setBufferSize(xxx) to increase the default value.

But do you need MQTT features? You could use just a Socket to your server

What hardware are you using to send the data? What format is it?

Great thank you for the information. My code is also posted now. I do not use the pubsubclient in this current code

I am using esp32 and sim7000g module. The cost is posted above.

is there any particular reason why you store your sensor data in the structure as text?

typedef struct struct_message {

  char depth1[10];
  char depth2[10];

why not store as integers, e.g.

typedef struct struct_message {

  int16_t  depth1;
  int16_t  depth2;

or if your require real numbers as floats
you could possibly then transmit the complete structure in binary significantly reducing the number of bytes in each transmission
also as @J-M-L asked in post 2 do you require the complexity of MQTT?
possibly a simple TCP or UDP client/server would simplify the communication

What would storing as integers help me do differently? The data I am sending is like:

x:0.0023,y:0.03345,z:9.8652,T:14:03:02:304,x:0.1023,y:0.43345,z:9.7652,T:14:03:02:316

In a text based (ASCII) communication the string
x:0.0023,y:0.03345,z:9.8652,T:14:03:02:304
uses up 42 (magic!) bytes without a trailing null. So you would send 42 bytes in the communication and I assume you could get more digits (6?) in your x, y and z probably so it could be 47 or more bytes

In a binary protocol you would send 3 floats (x, y and z) = 12 bytes and possibly a time_t type for T so 4 bytes = 16 bytes

you would use up only ~1/3rd of the bandwidth if you were to send the info in binary.

(it's not totally exact as you need to add some sort of start marker / end marker and a few control stuff but you get the idea)

as I said in post 6 if you require real numbers use float

typedef struct struct_message {

  float depth1;
 float depth2;

the main idea is if you transmit a complete structure in binary it can significantly reduce the overall volume of data
do you require MQTT? just transmit UDP datagrams?

Great thank you! How can I send a complete structure in binary? Could you give me just a small example? And I do not have to have MQTT, just trying to capture the 72 pieces of data (XYZ and time) per second that I am sampling. I am not familiar with UDP datagrams :frowning:

have a look there

ESP client sending UDP packets to a Python program on the server side

see how-to-send-a-udp-packet-to-a-gprs-module which gives example code for a SIM800 transmitting a UDP packet

Great!! Thank you so much Jackson! So if I did not covert to binary and changed all 4: (XYZ and Time) to floats, would that not also take up only 16 bytes?

Hey Horace, Yes for the depth I will get only values over 0, never negative. For the accelerometers I will get negative, 0, and positive. So would it be better to change all to floats? Or what if I called them char[4] or char[5] instead of char[10]?

if the original results you get from a sensor is an integer store it as an integer, if a float store it as a float, etc
convert to text when you wish to present the data to a human reader
when you convert from an internal binary representation to text you can loose precision

what do you wish to do with the information when you get it to the server? e.g. store in a database, view in a HTML page, process it in some program, plot some graphs, ???

Sorry, but as far I see, you understand nothing about formats of your own data.
You don't need " change it to floats". Look at your code. You receive data from accelerometer already as floats. And then you youself convert it to text string like char[10].
Why did you convert them?
Send them as is, just send data received from the accelerometer library.

Your accelerometer likely gives you an int16_t typed value (2 bytes signed integer) that you later convert using some knowledge of the configuration of your hardware to the float.

You could decide to send the raw value (2 bytes) instead of the float value (4 bytes) and let the recipient do the maths

There is some related discussion in another topic about this project:

I have closed that topic in order to limit all further discussion on the subject to this topic.

an example of transmitting a structure containing different data types from an ESP32 to a PC in binary
UDP client ESP32 code

// ESP32 UDP client sending datagrams to a UDP server

//  from https://github.com/evothings/evothings-examples/blob/master/examples/arduino-led-onoff-tcp/arduinowifi/arduinowifi/arduinowifi.ino

#include <WiFi.h>
#include <WiFiUdp.h>

// network SSID (network name). and network password.
char ssid[] = "xxxxxxxt";
char pass[] = "123456789";

// network key Index number (needed only for WEP).
int keyIndex = 0;

// UDP information
IPAddress udpServer(192, 168, 1, 68);
#define UDP_PORT 3000
WiFiUDP udp;

// UDP Datagram
struct __attribute__((packed)) UDPDatagram {
  uint16_t seq;                          // sequence number
  int16_t sdata;                         // 16 bit integer data
  int32_t idata;                         // 32 bit integer data
  float fdata;                           // float data
  uint16_t crc;                          // crc check
} udpDatagram = { 0, 10, 10, 3.14, 0 };  // initial values

void setup() {
  Serial.begin(115200);
  // Wait for serial port to connect. Needed for Leonardo only
  while (!Serial)
    ;
  delay(1000);
  Serial.println();
  Serial.println("ESP32 WiFi UDP client - send UDP datagrams to server");
  WiFi.mode(WIFI_STA);  // Connect to Wifi network.
  WiFi.begin(ssid, pass);
  Serial.println("");
  // Wait for connection
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.print("\nserver IP address: ");
  Serial.println(udpServer);
  udp.begin(UDP_PORT);
  Serial.print("server udp port ");
  Serial.println(UDP_PORT);
}

void loop() {
  // generate crc check - in this case a simple checksum
  udpDatagram.crc = 0;
  Serial.print("Datagram data ");
  for (int i = 0; i < sizeof(udpDatagram) - 2; i++) {
    Serial.print((uint8_t)((uint8_t *)&udpDatagram)[i], HEX);
    Serial.print(' ');
    udpDatagram.crc += ((uint8_t *)&udpDatagram)[i];
  }
  // Send Packet to UDP server
  udp.beginPacket(udpServer.toString().c_str(), UDP_PORT);
  int len = udp.write((const uint8_t *)&udpDatagram, sizeof(udpDatagram));
  udp.endPacket();
  Serial.print("\nudp datagram transmitted length ");
  Serial.print(len);
  Serial.print(" seq ");
  Serial.print(udpDatagram.seq++);
  Serial.print(" sdata ");
  Serial.print(udpDatagram.sdata);
  Serial.print(" idata ");
  Serial.print(udpDatagram.idata);
  Serial.print(" fdata ");
  Serial.print(udpDatagram.fdata);
  Serial.print(" crc = ");
  Serial.println(udpDatagram.crc);
  udpDatagram.crc = 0;  // update data values for tests
  udpDatagram.sdata += 10;
  udpDatagram.idata += 25;
  udpDatagram.fdata += 5.0f;
  delay(10000);
}

UDP server PC code compiled using the GNU GPP C++ compiler

// udp-server.cpp - simple UDP datagram server
//   receives datagrams from client and displays contents

#ifdef __WIN32
  #include <winsock.h>          // for windows
  #define socklen_t int
#else
  #include <arpa/inet.h>        // for UNIX
  #include <netdb.h>
  #define errno h_errno
#endif
#include <stdio.h>
#include <unistd.h>
#include <iostream>
#include <iomanip>
#include <cstring>
#include <cstdlib>


#define MAX_MSG 100
#define LINE_ARRAY_SIZE (MAX_MSG+1)

// UDP Datagram
struct __attribute__((packed))  UDPDatagram {
  uint16_t seq;    // sequence number
  int16_t sdata;  // 16 bit integer data
  int32_t idata;  // 32 bit integer data
  float fdata;    // float data
  uint16_t crc;    // crc check
} udpDatagram = { 0, 10, 10, 3.14, 0 };   // initial values

using namespace std;

// get and display IP address
void displayIPaddress(void)
{
      struct hostent *he;
      struct sockaddr_in sin;
      char machine_name[ 300 ];
      // get host computer name
      if (gethostname (machine_name, sizeof (machine_name)))
        {
          perror ("gethostname");
          system("pause"); exit(-1);
        }

     // get host information
     again:
      he = gethostbyname (machine_name);
      if (he == NULL)
        {
          if (errno == TRY_AGAIN)  goto again;
          perror ("gethostbyname");
          system("pause"); exit(-1);
        }

      // extract IP address and display it
      memset(&sin, 0,  sizeof (struct sockaddr_in));
      sin.sin_family = AF_INET;
      sin.sin_port = htons (80);
      memcpy (&sin.sin_addr , he->h_addr_list[ 0 ], he->h_length);
      cout << "Host " << machine_name << " IP address " <<  inet_ntoa (sin.sin_addr) << endl;
    }

int main()
{
  int listenSocket, i;
  unsigned short int listenPort;
  socklen_t clientAddressLength;
  struct sockaddr_in clientAddress, serverAddress;
  char line[LINE_ARRAY_SIZE];
   #ifdef __WIN32            // windows WINSOCK startup
      WSAData wsaData;
      if (WSAStartup(MAKEWORD(1, 1), &wsaData) != 0) {
          return 255;
      }
  #endif
  displayIPaddress();
  cout << "Enter port number to listen on (between 1500 and 65000): ";
  cin >> listenPort;
  // Create socket for listening for client connection requests.
  listenSocket = socket(AF_INET, SOCK_DGRAM, 0);
  if (listenSocket < 0)
    { perror ( "cannot create listen socket"); system("pause");  return -1;  }

  // Bind listen socket to listen port.  First set various fields in
  // the serverAddress structure, then call bind().
  // htonl() and htons() convert long integers and short integers
  // (respectively) from host byte order (on x86 this is Least
  // Significant Byte first) to network byte order (Most Significant
  // Byte first).
  serverAddress.sin_family = AF_INET;
  serverAddress.sin_addr.s_addr = htonl(INADDR_ANY);
  serverAddress.sin_port = htons(listenPort);

  if (bind(listenSocket, (struct sockaddr *) &serverAddress,  sizeof(serverAddress)) < 0)
      {  perror ("cannot bind socket"); system("pause"); return -1; }
  // Wait for connections from clients.
  // This is a non-blocking call; i.e., it registers this program with
  // the system as expecting connections on this socket, and then
  // this thread of execution continues on.
  listen(listenSocket, 5);
  cout << "Waiting for UDP datagram on port " << listenPort << "\n";
  uint16_t seq=0, errors=0;
  while (1) {
    int length;
    clientAddressLength = sizeof(clientAddress);
    memset(line, 0x0, LINE_ARRAY_SIZE);
    // receive datagram
    if ((length=recvfrom(listenSocket, line, MAX_MSG, 0,(struct sockaddr *) &clientAddress, &clientAddressLength)) < 0)
        {   perror ( "  recvfrom() failed "); system("pause");  return -1; }
    // show the client's IP address and port number and the received bytes
    cout << "\nFrom " << inet_ntoa(clientAddress.sin_addr) << ":" << ntohs(clientAddress.sin_port)
         << " Received: " << dec <<  length << " bytes: " ;
    for (i = 0; i < length-2; i++)
         cout << " " << setw(2) << showbase << hex << (int) (line[i] & 0xff);
    cout << endl;
    // if datagram is correct size copy it into structure and display contents
    if(sizeof(udpDatagram) == length) {
        memcpy ((void*) &udpDatagram, (void*) line, length);
        cout << dec << "seq " << udpDatagram.seq << " sdata " << udpDatagram.sdata << " idata " << udpDatagram.idata
            << " fdata " << udpDatagram.fdata  << " crc " << udpDatagram.crc ;
    // check CRC by calculating it and comparing with received value
    uint16_t crc=0;
    for (int i = 0; i < sizeof(udpDatagram) - 2; i++)
        crc += ((uint8_t *)&udpDatagram)[i];
    if(crc != udpDatagram.crc)
         cout << "\n ERROR! CRC received " << udpDatagram.crc << " calculated " << crc << " errors " << ++errors << endl;
    else cout << " CRC OK " << " errors " << errors<< endl;
    // check sequence number
    if(seq != udpDatagram.seq)
        cout << "ERROR! seq expected " << seq << " received " << udpDatagram.seq << " errors " << ++errors << endl;
    seq=udpDatagram.seq+1;      // update for next time
    }
  }
}

ESP32 serial monitor

ESP32 WiFi UDP client - send UDP datagrams to server

.....................
server IP address: 192.168.1.68
server udp port 3000
Datagram data 0 0 A 0 A 0 0 0 C3 F5 48 40 
udp datagram transmitted length 14 seq 0 sdata 10 idata 10 fdata 3.14 crc = 596
Datagram data 1 0 14 0 23 0 0 0 71 3D 2 41 
udp datagram transmitted length 14 seq 1 sdata 20 idata 35 fdata 8.14 crc = 297
Datagram data 2 0 1E 0 3C 0 0 0 71 3D 52 41 
udp datagram transmitted length 14 seq 2 sdata 30 idata 60 fdata 13.14 crc = 413
Datagram data 3 0 28 0 55 0 0 0 B8 1E 91 41 
udp datagram transmitted length 14 seq 3 sdata 40 idata 85 fdata 18.14 crc = 552
Datagram data 4 0 32 0 6E 0 0 0 B8 1E B9 41 
udp datagram transmitted length 14 seq 4 sdata 50 idata 110 fdata 23.14 crc = 628
Datagram data 5 0 3C 0 87 0 0 0 B8 1E E1 41 
udp datagram transmitted length 14 seq 5 sdata 60 idata 135 fdata 28.14 crc = 704
Datagram data 6 0 46 0 A0 0 0 0 5C 8F 4 42 
udp datagram transmitted length 14 seq 6 sdata 70 idata 160 fdata 33.14 crc = 541
Datagram data 7 0 50 0 B9 0 0 0 5C 8F 18 42 
udp datagram transmitted length 14 seq 7 sdata 80 idata 185 fdata 38.14 crc = 597
Datagram data 8 0 5A 0 D2 0 0 0 5C 8F 2C 42 
udp datagram transmitted length 14 seq 8 sdata 90 idata 210 fdata 43.14 crc = 653
Datagram data 9 0 64 0 EB 0 0 0 5C 8F 40 42 
udp datagram transmitted length 14 seq 9 sdata 100 idata 235 fdata 48.14 crc = 709
Datagram data A 0 6E 0 4 1 0 0 5C 8F 54 42 
udp datagram transmitted length 14 seq 10 sdata 110 idata 260 fdata 53.14 crc = 510
Datagram data B 0 78 0 1D 1 0 0 5C 8F 68 42 
udp datagram transmitted length 14 seq 11 sdata 120 idata 285 fdata 58.14 crc = 566
Datagram data C 0 82 0 36 1 0 0 5C 8F 7C 42 
udp datagram transmitted length 14 seq 12 sdata 130 idata 310 fdata 63.14 crc = 622
.............
Datagram data 26 6 86 3D C0 99 0 0 1F 9 F6 45 
udp datagram transmitted length 14 seq 1574 sdata 15750 idata 39360 fdata 7873.14 crc = 939
Datagram data 27 6 90 3D D9 99 0 0 1F 31 F6 45 
udp datagram transmitted length 14 seq 1575 sdata 15760 idata 39385 fdata 7878.14 crc = 1015
Datagram data 28 6 9A 3D F2 99 0 0 1F 59 F6 45 
udp datagram transmitted length 14 seq 1576 sdata 15770 idata 39410 fdata 7883.14 crc = 1091
Datagram data 29 6 A4 3D B 9A 0 0 1F 81 F6 45 
udp datagram transmitted length 14 seq 1577 sdata 15780 idata 39435 fdata 7888.14 crc = 912
Datagram data 2A 6 AE 3D 24 9A 0 0 1F A9 F6 45 
udp datagram transmitted length 14 seq 1578 sdata 15790 idata 39460 fdata 7893.14 crc = 988
Datagram data 2B 6 B8 3D 3D 9A 0 0 1F D1 F6 45 
udp datagram transmitted length 14 seq 1579 sdata 15800 idata 39485 fdata 7898.14 crc = 1064
Datagram data 2C 6 C2 3D 56 9A 0 0 1F F9 F6 45 
udp datagram transmitted length 14 seq 1580 sdata 15810 idata 39510 fdata 7903.14 crc = 1140
Datagram data 2D 6 CC 3D 6F 9A 0 0 1F 21 F7 45 
udp datagram transmitted length 14 seq 1581 sdata 15820 idata 39535 fdata 7908.14 crc = 961
Datagram data 2E 6 D6 3D 88 9A 0 0 1F 49 F7 45 
udp datagram transmitted length 14 seq 1582 sdata 15830 idata 39560 fdata 7913.14 crc = 1037

PC console output

Host BB-DELL2 IP address 192.168.1.68
Enter port number to listen on (between 1500 and 65000): 3000
Waiting for UDP datagram on port 3000

From 192.168.1.246:3000 Received: 14 bytes:   0  0 0xa  0 0xa  0  0  0 0xc3 0xf5 0x48 0x40
seq 0 sdata 10 idata 10 fdata 3.14 crc 596 CRC OK  errors 0

From 192.168.1.246:3000 Received: 14 bytes:  0x1  0 0x14  0 0x23  0  0  0 0x71 0x3d 0x2 0x41
seq 1 sdata 20 idata 35 fdata 8.14 crc 297 CRC OK  errors 0

From 192.168.1.246:3000 Received: 14 bytes:  0x2  0 0x1e  0 0x3c  0  0  0 0x71 0x3d 0x52 0x41
seq 2 sdata 30 idata 60 fdata 13.14 crc 413 CRC OK  errors 0

From 192.168.1.246:3000 Received: 14 bytes:  0x3  0 0x28  0 0x55  0  0  0 0xb8 0x1e 0x91 0x41
seq 3 sdata 40 idata 85 fdata 18.14 crc 552 CRC OK  errors 0

From 192.168.1.246:3000 Received: 14 bytes:  0x4  0 0x32  0 0x6e  0  0  0 0xb8 0x1e 0xb9 0x41
seq 4 sdata 50 idata 110 fdata 23.14 crc 628 CRC OK  errors 0

From 192.168.1.246:3000 Received: 14 bytes:  0x5  0 0x3c  0 0x87  0  0  0 0xb8 0x1e 0xe1 0x41
seq 5 sdata 60 idata 135 fdata 28.14 crc 704 CRC OK  errors 0

From 192.168.1.246:3000 Received: 14 bytes:  0x6  0 0x46  0 0xa0  0  0  0 0x5c 0x8f 0x4 0x42
seq 6 sdata 70 idata 160 fdata 33.14 crc 541 CRC OK  errors 0

From 192.168.1.246:3000 Received: 14 bytes:  0x7  0 0x50  0 0xb9  0  0  0 0x5c 0x8f 0x18 0x42
seq 7 sdata 80 idata 185 fdata 38.14 crc 597 CRC OK  errors 0

From 192.168.1.246:3000 Received: 14 bytes:  0x8  0 0x5a  0 0xd2  0  0  0 0x5c 0x8f 0x2c 0x42
seq 8 sdata 90 idata 210 fdata 43.14 crc 653 CRC OK  errors 0

From 192.168.1.246:3000 Received: 14 bytes:  0x9  0 0x64  0 0xeb  0  0  0 0x5c 0x8f 0x40 0x42
seq 9 sdata 100 idata 235 fdata 48.14 crc 709 CRC OK  errors 0

From 192.168.1.246:3000 Received: 14 bytes:  0xa  0 0x6e  0 0x4 0x1  0  0 0x5c 0x8f 0x54 0x42
seq 10 sdata 110 idata 260 fdata 53.14 crc 510 CRC OK  errors 0

From 192.168.1.246:3000 Received: 14 bytes:  0xb  0 0x78  0 0x1d 0x1  0  0 0x5c 0x8f 0x68 0x42
seq 11 sdata 120 idata 285 fdata 58.14 crc 566 CRC OK  errors 0

From 192.168.1.246:3000 Received: 14 bytes:  0xc  0 0x82  0 0x36 0x1  0  0 0x5c 0x8f 0x7c 0x42
seq 12 sdata 130 idata 310 fdata 63.14 crc 622 CRC OK  errors 0

From 192.168.1.246:3000 Received: 14 bytes:  0xd  0 0x8c  0 0x4f 0x1  0  0 0xae 0x47 0x88 0x42
seq 13 sdata 140 idata 335 fdata 68.14 crc 680 CRC OK  errors 0

From 192.168.1.246:3000 Received: 14 bytes:  0xe  0 0x96  0 0x68 0x1  0  0 0xae 0x47 0x92 0x42
seq 14 sdata 150 idata 360 fdata 73.14 crc 726 CRC OK  errors 0

From 192.168.1.246:3000 Received: 14 bytes:  0xf  0 0xa0  0 0x81 0x1  0  0 0xae 0x47 0x9c 0x42
seq 15 sdata 160 idata 385 fdata 78.14 crc 772 CRC OK  errors 0

From 192.168.1.246:3000 Received: 14 bytes:  0x10  0 0xaa  0 0x9a 0x1  0  0 0xae 0x47 0xa6 0x42
seq 16 sdata 170 idata 410 fdata 83.14 crc 818 CRC OK  errors 0
..................
From 192.168.1.246:3000 Received: 14 bytes:  0x43 0x5 0xa8 0x34 0x95 0x83  0  0 0x1f 0x91 0xd2 0x45
seq 1347 sdata 13480 idata 33685 fdata 6738.14 crc 1027 CRC OK  errors 0

From 192.168.1.246:3000 Received: 14 bytes:  0x44 0x5 0xb2 0x34 0xae 0x83  0  0 0x1f 0xb9 0xd2 0x45
seq 1348 sdata 13490 idata 33710 fdata 6743.14 crc 1103 CRC OK  errors 0

From 192.168.1.246:3000 Received: 14 bytes:  0x46 0x5 0xc6 0x34 0xe0 0x83  0  0 0x1f 0x9 0xd3 0x45
seq 1350 sdata 13510 idata 33760 fdata 6753.14 crc 1000 CRC OK  errors 0
ERROR! seq expected 1349 received 1350 errors 1

From 192.168.1.246:3000 Received: 14 bytes:  0x47 0x5 0xd0 0x34 0xf9 0x83  0  0 0x1f 0x31 0xd3 0x45
seq 1351 sdata 13520 idata 33785 fdata 6758.14 crc 1076 CRC OK  errors 1

From 192.168.1.246:3000 Received: 14 bytes:  0x48 0x5 0xda 0x34 0x12 0x84  0  0 0x1f 0x59 0xd3 0x45
seq 1352 sdata 13530 idata 33810 fdata 6763.14 crc 897 CRC OK  errors 1

...................
From 192.168.1.246:3000 Received: 14 bytes:  0x25 0x6 0x7c 0x3d 0xa7 0x99  0  0 0x1f 0xe1 0xf5 0x45
seq 1573 sdata 15740 idata 39335 fdata 7868.14 crc 1118 CRC OK  errors 1

From 192.168.1.246:3000 Received: 14 bytes:  0x26 0x6 0x86 0x3d 0xc0 0x99  0  0 0x1f 0x9 0xf6 0x45
seq 1574 sdata 15750 idata 39360 fdata 7873.14 crc 939 CRC OK  errors 1

From 192.168.1.246:3000 Received: 14 bytes:  0x27 0x6 0x90 0x3d 0xd9 0x99  0  0 0x1f 0x31 0xf6 0x45
seq 1575 sdata 15760 idata 39385 fdata 7878.14 crc 1015 CRC OK  errors 1

From 192.168.1.246:3000 Received: 14 bytes:  0x28 0x6 0x9a 0x3d 0xf2 0x99  0  0 0x1f 0x59 0xf6 0x45
seq 1576 sdata 15770 idata 39410 fdata 7883.14 crc 1091 CRC OK  errors 1

From 192.168.1.246:3000 Received: 14 bytes:  0x29 0x6 0xa4 0x3d 0xb 0x9a  0  0 0x1f 0x81 0xf6 0x45
seq 1577 sdata 15780 idata 39435 fdata 7888.14 crc 912 CRC OK  errors 1

From 192.168.1.246:3000 Received: 14 bytes:  0x2a 0x6 0xae 0x3d 0x24 0x9a  0  0 0x1f 0xa9 0xf6 0x45
seq 1578 sdata 15790 idata 39460 fdata 7893.14 crc 988 CRC OK  errors 1

From 192.168.1.246:3000 Received: 14 bytes:  0x2b 0x6 0xb8 0x3d 0x3d 0x9a  0  0 0x1f 0xd1 0xf6 0x45
seq 1579 sdata 15800 idata 39485 fdata 7898.14 crc 1064 CRC OK  errors 1

From 192.168.1.246:3000 Received: 14 bytes:  0x2c 0x6 0xc2 0x3d 0x56 0x9a  0  0 0x1f 0xf9 0xf6 0x45
seq 1580 sdata 15810 idata 39510 fdata 7903.14 crc 1140 CRC OK  errors 1

From 192.168.1.246:3000 Received: 14 bytes:  0x2d 0x6 0xcc 0x3d 0x6f 0x9a  0  0 0x1f 0x21 0xf7 0x45
seq 1581 sdata 15820 idata 39535 fdata 7908.14 crc 961 CRC OK  errors 1

From 192.168.1.246:3000 Received: 14 bytes:  0x2e 0x6 0xd6 0x3d 0x88 0x9a  0  0 0x1f 0x49 0xf7 0x45
seq 1582 sdata 15830 idata 39560 fdata 7913.14 crc 1037 CRC OK  errors 1

the server performs sequence number and CRC checks - the above shows there has been a problem - a datagram was lost and there was sequence number error

one has to make sure that the data types and sizes are the same on both the transmitter and receiver - fairly straightforward with the above when both ends use C++ but more difficult if the languages are different, e.g. C++ client to a Java server (Java does not have unsigned data types)

1 Like

here's another example..
using Delphi, object pascal..
same structure, crc and seq checks..
did one small change to ino sketch, used my local broadcast address..

UDP Send

fun stuff.. ~q