Problem in formatting int array in client.read() with (uint8_t *) &

Hi there,

Maybe this section is more appropriate for my problem that is acqually posted at https://forum.arduino.cc/index.php?topic=684308.0

Substantially I have problem in formatting an array that I have to send over TCP from a client ESP32 Dev Board to a server on ARDUINO MEGA 2560.

that’s the sketch client side:

#include <WiFi.h>
///////////////////////////////////////////////////////////////////////////////////
// Wifi configuration
// Replace with your network credentials
const char* ssid = "netwroksssssfds";
const char* password = "passsssssss";
byte server[] = {xxx, xxx,xxx,xxx};  // web server IP (CORE)
WiFiClient client;

/**********  Setup    **********/
void setup(){
  // Serial port for debugging purposes
  Serial.begin(9600);
    WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    Serial.println("Connecting to WiFi..");
    delay(1000);
  }
  // connecting to server
  if (client.connect(server,1235)){
  Serial.print("Connected to Server: ");
  }
}

 
void loop(){
 
  // Sensors Output
  unsigned long Out0= 0;
  unsigned long Out1= 1;
  unsigned long Out2= 2;
  unsigned long Out3= 3;
  unsigned long Out4= 4;
  unsigned long Out5= 5;
  unsigned long Out6= 6;
  unsigned long Out7= 7;
  unsigned long Out8= 8;
  unsigned long Out9= 9;
  unsigned long Out10= 10;
  unsigned long Out11= 11;
  unsigned long Out12= 12;
  unsigned long sensorboxdata[] ={Out0, Out1, Out2, Out3, Out4, Out5,Out6,Out7,Out8,Out9,Out10,Out11,Out12};

  for (int i=0;i<=10;i++){
    Serial.print("Sensore numero ");
    Serial.println(i);
    Serial.println(sensorboxdata[i]);  // they are correct there
  }
  // Send data to Server
  if (client.connected()){
    Serial.println("sensorboxdatabyte to Server");
    client.write((uint8_t*) &sensorboxdata,sizeof(sensorboxdata));
    delay(10);   
  } else {
    Serial.println("Connection to Server lost, trying to reconnect...");
    if (client.connect(server,1234)){
      Serial.println("Connected to Server");
    }
    else {
      Serial.println("Unable to connect to Server!");
   
    }
  } 
 delay(3000);   
}

and the serial debug gives the right values:

19:34:33.563 → Sensore numero 0
19:34:33.563 → 0
19:34:33.563 → Sensore numero 1
19:34:33.609 → 1
19:34:33.609 → Sensore numero 2
19:34:33.609 → 2
19:34:33.609 → Sensore numero 3
19:34:33.643 → 3
19:34:33.643 → Sensore numero 4
19:34:33.690 → 4
19:34:33.690 → Sensore numero 5
19:34:33.690 → 5
19:34:33.690 → Sensore numero 6
19:34:33.728 → 6
19:34:33.728 → Sensore numero 7
19:34:33.728 → 7
19:34:33.728 → Sensore numero 8
19:34:33.764 → 8
19:34:33.764 → Sensore numero 9
19:34:33.764 → 9
19:34:33.764 → Sensore numero 10
19:34:33.811 → 10
19:34:33.811 → sensorboxdatabyte to Server

But when I read the array from the server side:

#include <SPI.h>               // SPI: for screen & ethernet
#include <Ethernet.h>
byte mac[] = {xxxxxxxx}; 
byte ip[] = { xxxxxxxx };
EthernetServer server(1234);
////////////////////////           SETUP                   /////////////////////////
void setup() {
  Serial.begin(9600);
  Ethernet.begin(mac); // Start Ethernet Connection _   Ethernet.begin(mac, ip);
  server.begin(); // start server
}
////////////////////////           LOOP                    /////////////////////////
void loop() {
  unsigned long sensorboxdata[13];
  // request data from sensor box
   Serial.print("Request data from sensor box");
   EthernetClient client = server.available(); // wait and assign client
   int size;
   unsigned long * sensordata = (unsigned long*)malloc(size);
   if (client) {
    Serial.println("client ready");
    if (size=client.available()){
        size = client.read((uint8_t *) sensordata, size);
        for (int i=0;i<=12;i++){
        sensorboxdata[i]=0;
        String str = String("") + sensordata[i];
        sensorboxdata[i]=str.toInt();
        Serial.print("Output #");
        Serial.println(i);
        Serial.println(str);
        Serial.println(String(sensorboxdata[i]));
        }
    }
   }
   else {
   Serial.println("No client available");
   }
      delay(5000);
}
////////////////////////////////////// loop end

… I got complete no sense output, with Output0 and Output7 / 12 correct, and others are wrong:

19:35:58.390 → Request data from sensor boxclient ready
19:35:58.424 → Output #0
19:35:58.458 → 0
19:35:58.458 → 0
19:35:58.458 → Output #1
19:35:58.458 → 131072
19:35:58.458 → 131072
19:35:58.458 → Output #2
19:35:58.492 → 808517632
19:35:58.492 → 808517632
19:35:58.543 → Output #3
19:35:58.543 → 859191089
19:35:58.543 → 859191089
19:35:58.543 → Output #4
19:35:58.543 → 655417
19:35:58.590 → 655417
19:35:58.590 → Output #5
19:35:58.590 → 3617076
19:35:58.590 → 3617076
19:35:58.590 → Output #6
19:35:58.643 → 942669878
19:35:58.643 → 942669878
19:35:58.643 → Output #7
19:35:58.643 → 56
19:35:58.643 → 56
19:35:58.643 → Output #8
19:35:58.690 → 8
19:35:58.690 → 8
19:35:58.690 → Output #9
19:35:58.690 → 9
19:35:58.690 → 9
19:35:58.690 → Output #10
19:35:58.690 → 10
19:35:58.744 → 10
19:35:58.744 → Output #11
19:35:58.744 → 11
19:35:58.744 → 11
19:35:58.744 → Output #12
19:35:58.744 → 12
19:35:58.744 → 12

What is going on?

Thanks in advance!

 int size;
   unsigned long * sensordata = (unsigned long*)malloc(size);

You should never use malloc in a C++ program. If you need an explicit heap allocation, use std::make_unique and an std::unique_ptr. In your case, simply use std::vector.
If you are a standard library writer, you might occasionally need new and delete, which replace malloc and free.

Your code is problematic because it uses malloc without ever freeing the memory (again, use std::vector instead), and because the size is never initialized.

Are you sure unsigned long is the same size on both platforms? Prefer uint32_t to be certain.

        String str = String("") + sensordata[i];
        sensorboxdata[i]=str.toInt();

Why do you first convert the integer to a string, and then to an integer again?

Pieter

Thanks Pieter for your reply!

Honestly I arrived pretty exhaust at this final part of the project and I had not time to study well what each function was doing...

"Why do you first convert the integer to a string, and then to an integer again?"

Honestly I don't know why I am doing this stuff... just copied around and found that it worked for one value. but then I had issue for the others!

Could you please be kind to explain precisely what I have to write? Given my lack of basis I don't have idea how to fix it.

I think that my intent is pretty clear: send numbers in array (I think also integer could be sufficient for example) from the client to the server and being sure to receive them in the correct order one time per minute.

Good mng all!

Got it sorted and I suspected it was a pretty stupid problem… But honestly I was floored by the fact that some values where correct!

Anyway the problem is about memory allocation of the array (sensordata). I sorted it out by assigning a big value to size, that indeed was not declared (honestly as said, I had no time to investigate properly in this part of the project and what these function were doing, my really bad). Then I used free(sensordata) to free the memory allocated and finally the server has been able to read correctly all the data!

Moreover as suggested by the good PieterP, nosense to convert the int to String and then back to int…
Sorry guys, I usually try to understand well each part of the code I am using, this time really exhausted about c stuff and misleaded from some correct values.

ANYWAY AS USUAL, THE ANSWER IS INSIDE YOU(R CODE)!!

Thanks so much for your patience!

PS: Here you are the server code in case some puppet like me will need in the future :smiley:

   int size=100; // <- before it was just declared, no value assigne
   int long * sensordata = (int long *)malloc(size);
   if (client) { 
    Serial.println("client ready");
    if (size=client.available()){
        size = client.read((uint8_t *) sensordata, size);
        for (int i=0;i<=12;i++){
        sensorboxdata[i]=sensordata[i]; // almost surely I can directly use sensordata instead of allocating 
        // a new  array... going to test it
        Serial.print("Output #");
        Serial.println(i);
        Serial.println(String(sensorboxdata[i]));
        }
        free(sensordata); // <- freeing up the memory on sensordata array
    }
   }

Your code still leaks when there’s no client available. That’s the exact reason why you shouldn’t be using malloc and free.
You’re also reading too much data, if you send more data to the server than expected, it’ll overflow your sensordata array, crashing your program and posing a security thread.

Since you know how many values the client will be sending, there’s no need to dynamically allocate anything.

The logic of your server’s client handling is incorrect as well. You have to check how many bytes are available before using the array. There is no guarantee that all values arrive at once, If the client were sending a single byte at a time, your code would fill the array with only one byte, and read uninitialized memory.

Here are some improvements, but I don’t have the hardware to test it:

[color=#00979c]void[/color] [color=#5e6d03]loop[/color][color=#000000]([/color][color=#000000])[/color] [color=#000000]{[/color]
  [color=#434f54]// Your comment was wrong, the server cannot request anything from the client[/color]
  [b][color=#d35400]Serial[/color][/b][color=#434f54].[/color][color=#d35400]print[/color][color=#000000]([/color][color=#005c5f]"Check if a client connection is available"[/color][color=#000000])[/color][color=#000000];[/color]
  [b][color=#d35400]EthernetClient[/color][/b] [color=#000000]client[/color] [color=#434f54]=[/color] [color=#000000]server[/color][color=#434f54].[/color][color=#d35400]available[/color][color=#000000]([/color][color=#000000])[/color][color=#000000];[/color] [color=#434f54]// wait and assign client[/color]
  [color=#5e6d03]if[/color] [color=#000000]([/color][color=#000000]client[/color][color=#000000])[/color] [color=#000000]{[/color]
    [b][color=#d35400]Serial[/color][/b][color=#434f54].[/color][color=#d35400]println[/color][color=#000000]([/color][color=#005c5f]"client ready"[/color][color=#000000])[/color][color=#000000];[/color]
    [color=#00979c]uint32_t[/color] [color=#000000]sensordata[/color][color=#000000][[/color][color=#000000]13[/color][color=#000000]][/color][color=#000000];[/color]
    [color=#5e6d03]while[/color] [color=#000000]([/color][color=#000000]client[/color][color=#434f54].[/color][color=#d35400]available[/color][color=#000000]([/color][color=#000000])[/color] [color=#434f54]<[/color] [color=#00979c]sizeof[/color][color=#000000]([/color][color=#000000]sensordata[/color][color=#000000])[/color] [color=#434f54]&&[/color] [color=#000000]client[/color][color=#000000])[/color]
      [color=#d35400]delay[/color][color=#000000]([/color][color=#000000]1[/color][color=#000000])[/color][color=#000000];[/color] [color=#434f54]// wait for data to arrive[/color]
    [color=#5e6d03]if[/color] [color=#000000]([/color][color=#000000]client[/color][color=#434f54].[/color][color=#d35400]available[/color][color=#000000]([/color][color=#000000])[/color] [color=#434f54]>=[/color] [color=#00979c]sizeof[/color][color=#000000]([/color][color=#000000]sensordata[/color][color=#000000])[/color][color=#000000])[/color][color=#000000]{[/color]
      [color=#000000]client[/color][color=#434f54].[/color][color=#d35400]read[/color][color=#000000]([/color][color=#00979c]reinterpret_cast[/color][color=#434f54]<[/color][color=#00979c]uint8_t[/color] [color=#434f54]*[/color][color=#434f54]>[/color][color=#000000]([/color][color=#000000]sensordata[/color][color=#000000])[/color][color=#434f54],[/color] [color=#00979c]sizeof[/color][color=#000000]([/color][color=#000000]sensordata[/color][color=#000000])[/color][color=#000000])[/color][color=#000000];[/color]
      [color=#00979c]uint8_t[/color] [color=#000000]i[/color] [color=#434f54]=[/color] [color=#000000]0[/color][color=#000000];[/color]
      [color=#5e6d03]for[/color] [color=#000000]([/color][color=#00979c]auto[/color] [color=#000000]value[/color] [color=#434f54]:[/color] [color=#000000]sensordata[/color][color=#000000])[/color][color=#000000]{[/color]
        [b][color=#d35400]Serial[/color][/b][color=#434f54].[/color][color=#d35400]print[/color][color=#000000]([/color][color=#005c5f]"Output #"[/color][color=#000000])[/color][color=#000000];[/color]
        [b][color=#d35400]Serial[/color][/b][color=#434f54].[/color][color=#d35400]println[/color][color=#000000]([/color][color=#000000]i[/color][color=#434f54]++[/color][color=#000000])[/color][color=#000000];[/color]
        [b][color=#d35400]Serial[/color][/b][color=#434f54].[/color][color=#d35400]println[/color][color=#000000]([/color][color=#000000]value[/color][color=#000000])[/color][color=#000000];[/color]
      [color=#000000]}[/color]
    [color=#000000]}[/color] [color=#5e6d03]else[/color] [color=#000000]{[/color]
      [b][color=#d35400]Serial[/color][/b][color=#434f54].[/color][color=#d35400]println[/color][color=#000000]([/color][color=#005c5f]"Client didn't send enough data"[/color][color=#000000])[/color][color=#000000];[/color]
    [color=#000000]}[/color]
  [color=#000000]}[/color] [color=#5e6d03]else[/color] [color=#000000]{[/color]
    [b][color=#d35400]Serial[/color][/b][color=#434f54].[/color][color=#d35400]println[/color][color=#000000]([/color][color=#005c5f]"No client available"[/color][color=#000000])[/color][color=#000000];[/color]
  [color=#000000]}[/color]
  [color=#d35400]delay[/color][color=#000000]([/color][color=#000000]5000[/color][color=#000000])[/color][color=#000000];[/color] [color=#434f54]// Why the delay here? [/color]
  [color=#434f54]// The code above only executes when a client is available anyway,[/color]
  [color=#434f54]// there's no need to wait, in the worst case it might even cause[/color]
  [color=#434f54]// the client to timeout.[/color]
[color=#000000]}[/color]