I am using an ESP32 to do some network stuff. I am using the WiFiClient library, and sending data works fine (the write() function can send one or multiple bytes). However, it seems that the read() function only reads one byte at a time. I could implement a while() to read all the bytes, but this seems very, very inefficient, especially on MCUs with limited CPU resources.
Is there some way (perhaps a different library) to work directly with sockets, or to be able to read multiple bytes at once in a single call?
void loop() {
static WiFiClient client;
static int16_t seqExpected = 0;
if (!client)
client = server.available(); // Listen for incoming clients
if (client) { // if client connected
if (!alreadyConnected) {
// clead out the input buffer:
client.flush();
Serial.println("We have a new client");
alreadyConnected = true;
}
// if data available from client read and display it
int length;
float value;
if ((length = client.available()) > 0) {
//str = client.readStringUntil('\n'); // read entire response
Serial.printf("Received length %d - ", length);
// if data is correct length read and display it
if (length == sizeof(value)) {
client.readBytes((char*)&value, sizeof(value));
Serial.printf("value %f \n", value);
} else
while (client.available()) Serial.print((char)client.read()); // discard corrupt packet
}
}
}
Thanks! You are right, I was looking at just part of the error message (where it complained that the function candidate had 0 parameters). Later on it was complaining about incompatible types, I had to cast a pointer which solved it. I am still a bit new to Arduino, I am used to work with sockets and lower level stuff
read() returns a single byte readBytes() returns a number of bytes
client.readBytes((char*)&value, sizeof(value));
the firdt parameter is a pointer to the destination byte array second parameter is the number of bytes to attempt to read - returns the number of bytes read from the stram
make sure you cast the destination to (byte*) or as above (char *)
The data should not come byte by byte, it should come in a buffer. I mean, it may come byte by byte at a very low level, but any WiFi hardware puts it in a buffer before being presented to the driver.
Even if 1 were not true, calling a function millions of times to download a picture is very slow, even on a PC, let alone on a 240Mhz MCU.
All data comes byte by byte, of course, but yes it is buffered and you can read chunks..
But you do have to watch out for larger transfers, like pics, you can't read it all in one go, buffers are not larger enough, they will be sent in chunks the size of the current MTU of the network, usually around 1,500 bytes..
You need to create a buffer to store entire size and read in chunks and add to your buffer..
I noticed this when I added ota to nards, was toying with different buffer sizes, when i went over the MTU size, things got funny..
That's when I added the RECV_EXTRA block to my _checkIncoming()..
Not a problem you notice when sending, only receiving..
I have over 20 years of network programming experience in C I also played with the ESP8266 back in the day (2016 or so) when I discovered that by default, the WiFi speed was very slow (something less than 300 kbps). By tweaking the MTU I managed to get it at 2-3MB/s.
Since then, things have changed and WiFi works pretty well, but I don't have that much experience with Arduino (I mean, I can do the basic things, but I am not that good at Arduino specific details).
It doesn't help that the Arduino documentation is VERY poor. On the official site, the WiFiclient won't even mention that you can read/write multiple bytes at once. You have to look on the source code to see that...
#include <WiFi.h>
const char *ssid = "your-SSID";
const char *password = "your-PASSWORD";
const char *host = "example.com";
const int port = 80;
void setup() {
Serial.begin(115200);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(1000);
Serial.println("Connecting to WiFi...");
}
Serial.println("Connected to WiFi");
// Use WiFiClient to connect to a remote server
WiFiClient client;
if (client.connect(host, port)) {
Serial.println("Connected to server");
// Send data to the server
client.write("Hello, server!");
// Read multiple bytes from the server
char buffer[256];
int bytesRead = client.readBytes(buffer, sizeof(buffer));
// Process the received data
if (bytesRead > 0) {
Serial.print("Received data: ");
Serial.write(buffer, bytesRead);
} else {
Serial.println("No data received");
}
// Close the connection
client.stop();
} else {
Serial.println("Connection to server failed");
}
}
void loop() {
// Your code here
}