WiFiClient.available() hangs

My Arduino hangs. By putting some Serial.print between the code, I believe it hangs at WiFiClient.available(). Here is the relevant code:

void checkOK() {
  Serial.println("Checking available");
  if (client.available()) {
    Serial.println("reading");
    uint8_t simplifiedReply = client.read();
    Serial.println("read");
    if (simplifiedReply == 1) {
      allowSend = true;
      Serial.println("flag send");
    }
  }
  Serial.println("Checking available complete");
}

client is initialized as WiFiClient client;
checkOK() is called in the loop if allowSend is false.
The server send reply at ~35ms interval

The Serial log:

[...]
Checking available complete
Checking available
Checking available complete
Checking available
Checking available complete
Checking available
reading
read
flag send
Checking available complete
Checking available
Checking available complete
Checking available
Checking available complete
Checking available
Checking available complete
Checking available
Checking available complete
Checking available
Checking available complete
Checking available

After running smoothly for several minutes (non-deterministic), it stuck after printing "Checking available", so I believe it hangs in client.available().

I am running on Arduino Nano 33 IOT. Any comments would be much appreciated.

Edit 1:

I removed the available check which looks redundant. But I still have the same problem, now it stuck at client.read().

void checkOK() {
  Serial.println("reading reply");
  uint8_t simplifiedReply = client.read();
  Serial.println(simplifiedReply);
  if (simplifiedReply == 1) {
    allowSend = true;
  }
}

Log:

[...]
255
reading reply
255
reading reply
255
reading reply
255
reading reply
255
reading reply
255
reading reply

client.read() gives 255(-1) if there is nothing to read. It stuck at reading again. I think either I damaged client data or there is a bug within WiFiClient code.

Edit 2:

I changed the reply interval from ~35ms to ~100ms, now it runs for 1 hour non-stop without a problem. However, sometimes the read function still hangs for short period of time, sometimes as long as 6 seconds. Now, I am more inclined to believe it is a hardware problem.

Please follow the advice given in the link below when posting code, in particular the section entitled 'Posting code and common code problems'

Use code tags (the </> icon above the compose window) to make it easier to read and copy for examination

Thank you for the advice. I am posting the full sketch code following Edit2 here:

#include <WiFiNINA.h>

#include "wpa_cred.h"
#include "device_descriptor.h"

int status = WL_IDLE_STATUS;             // the Wi-Fi radio's status
int ledState = LOW;                       //ledState used to set the LED
unsigned long previousMicrosInfo = 0;     //will store last time Wi-Fi information was updated
unsigned long previousMicrosReport = 0;
const unsigned long reportInterval = 100000;            // interval at which to update the board information
const unsigned long collectInterval = 1000;            // interval at which to collect analog signal
byte buffer[4000]; // micros (4 bytes) + uint16_t (2 bytes) * 3 = 10 bytes per frame
uint16_t bufferPointer = 4; // four bytes are for total byte counts
uint16_t maxbuffer = 2004; // 4 + 10 * 200 = 1004, that's 200 frames
bool allowSend = true;

IPAddress server(192, 168, 137, 1);
WiFiClient client;

uint32_t reverseWordEndianness(uint32_t src) { // use -O3 will get rid of the call stack
  uint32_t dest = 0;
  asm ("REV %0, %1"
    : "=r" (dest)
    : "r" (src));

  return dest;
}

void connectToWifi() {
  // attempt to connect to Wi-Fi network:
  while (status != WL_CONNECTED) {
    Serial.print("Attempting to connect to network: ");
    Serial.println(ssid);
    // Connect to WPA/WPA2 network:
    status = WiFi.begin(ssid, pass);
  
    // wait 10 seconds for connection:
    delay(10000);
  }

  // you're connected now, so print out the data:
  Serial.println("You're connected to the network");
  Serial.println("---------------------------------------");
}

void sendDeviceDescriptor() {
  uint32_t dataLength = strlen(descriptor);
  uint32_t dataLengthBE = reverseWordEndianness(dataLength);
  client.write(reinterpret_cast<byte*>(&dataLengthBE), 4);
  size_t writtenLen = client.write(descriptor, dataLength); // assume utf-8 works
  allowSend = false;
  Serial.print("descriptor bytes sent: ");
  Serial.println(writtenLen);
}

void connectToPainlabControlPanel() {
  while (1) {
    if (client.connect(server, 8124)) {
      // connect to pain lab control panel
      Serial.println("Connected to control panel");
      break;
    }
    Serial.println("Can't connect to pain lab control panel");
    delay(10000);
  }

  Serial.println("Sending descriptor");
  sendDeviceDescriptor();
}

void setup() {
  analogReadResolution(16); // padded to fit uint16_t

  //Initialize serial and wait for port to open:
  Serial.begin(9600);
  // while (!Serial);

  // set the LED as output
  pinMode(LED_BUILTIN, OUTPUT);

  connectToWifi();
  connectToPainlabControlPanel();
  Serial.println("setup completed");
}

void printNetworkInfo() {
  Serial.println("Board Information:");
  // print your board's IP address:
  IPAddress ip = WiFi.localIP();
  Serial.print("IP Address: ");
  Serial.println(ip);

  // print your network's SSID:
  Serial.println();
  Serial.println("Network Information:");
  Serial.print("SSID: ");
  Serial.println(WiFi.SSID());

  // print the received signal strength:
  long rssi = WiFi.RSSI();
  Serial.print("signal strength (RSSI):");
  Serial.println(rssi);
  Serial.println("---------------------------------------");
}

#define COPY_AND_ADVANCE(data) \
  {                                                       \
    memcpy(buffer + bufferPointer, reinterpret_cast<byte*>(&data), sizeof(data));   \
    bufferPointer += sizeof(data);\
  }

void readAndPushFrameIntoBuffer() {
  if (bufferPointer > maxbuffer) {
    Serial.print("Frame dropped, allowSend: ");
    Serial.println(allowSend);
    bufferPointer = 4;
  }
  unsigned long ts = micros();
  // Remember to change ADC clock to at least DIV64
  uint16_t a0_reading = analogRead(A0); // GSR
  uint16_t a2_reading = analogRead(A2); // Heart Rate
  uint16_t a4_reading = analogRead(A4); // Myoware muscle sensor

  COPY_AND_ADVANCE(ts);
  COPY_AND_ADVANCE(a0_reading);
  COPY_AND_ADVANCE(a2_reading);
  COPY_AND_ADVANCE(a4_reading);
}

void checkOK() {
  //Serial.println("reading reply");
  uint8_t simplifiedReply = client.read();
  //Serial.println(simplifiedReply);
  if (simplifiedReply == 1) {
    allowSend = true;
  }
}

void loop() {
 if (!allowSend) {
    checkOK();
 }
 
 unsigned long currentMicrosInfo = micros();

 // check if the time after the last update is bigger the interval
 if (currentMicrosInfo - previousMicrosInfo >= collectInterval) {
   previousMicrosInfo = currentMicrosInfo;
   readAndPushFrameIntoBuffer();
 }
 
 //Serial.println(currentMicrosInfo - previousMicrosReport);
 if (allowSend && bufferPointer > 4) {
    if (currentMicrosInfo - previousMicrosReport >= reportInterval) {
      previousMicrosReport = currentMicrosInfo;

      *(reinterpret_cast<uint32_t*>(buffer)) = reverseWordEndianness(bufferPointer - 4); // write four BE bytes to buffer header
      
      client.write(buffer, bufferPointer); // ~3.5ms
      bufferPointer = 4;
      allowSend = false;

      // if the LED is off turn it on and vice-versa:
      if (ledState == LOW) {
        ledState = HIGH;
      } else {
        ledState = LOW;
      }

      // set the LED with the ledState of the variable:
      digitalWrite(LED_BUILTIN, ledState);
    }
 }

}

Basically, it is a program that reads from analog pins every 1ms (collectInterval) and pack them into batch frames (with 4 big endian leading bytes specifiying the size), write to the server every 100ms ( reportInterval), and receive one byte acknowledgement response from the server to allow to send another batch frames. In Edit2, I changed reportInterval from 30ms to 100ms (also increase maxBuffer), then it won't hang (still hangs for several seconds from time to time, so I am considering changing boards or using serial communication).
Note to keep three analog read complete within 1ms, I have changed ADC_CTRLB_PRESCALER_DIV512 to ADC_CTRLB_PRESCALER_DIV64 mannually.

I will try to make a replicable version using simple server script and minimised intense read / write arduino sketch. But if anyone knows there is a limit in the hardware, then I don't need to do this...