stream.available()

I want to use client.available() in the following code snippit to evaluate the length of the Ethernet data available to be read:

EthernetClient client = server.available();
  while (client.connected()) {
    int maximumLength;
    int receivedPacketSize = client.available();
    if (receivedPacketSize >= serverBufferSize) maximumLength = serverBufferSize;
    else maximumLength = receivedPacketSize;
    for (int i; i <= maximumLength; i++) {
      char character = client.read();
      if (character == '\r') {
        serverBuffer[i] = '\0';
        break;
      }
      else {
        serverBuffer[i] = character;
        serverBuffer[i + 1] = '\0';
      }
    }

I am worried that if I do it the way I have written, given the speed of the MCU, I will see the client connected, read the bytes available and enter the loop before the client has finished sending the first line.

I have experienced this behavior with slow serial, and solved it by while Serial.available().

However, I need to know the size of the packet before I start reading it to make my evaulations of the length…

Should I be concerned?

Is there a more appropriate solution?

I am worried that if I do it the way I have written, given the speed of the MCU, I will see the client connected, read the bytes available and enter the loop before the client has finished sending the first line.

Why is that a problem? You may need to call that function over and over, to read all the client data.

Of course, you could add a delay() and hope like hell that the server has sent all the data by then. I'd recommend delay(86400000UL);. Even the slowest server should be done by then.

    for (int i; i <= maximumLength; i++) {

I would worry that ‘i’ has been left uninitialized.

PaulS:
Why is that a problem?

I don't mind calling the loop each time there is a client.connected, but I do want to read the first line, the whole first line and nothing but the first line.

johnwasser:
I would worry that 'i' has been left uninitialized.

I initialize it in the "for" loop.
I've run the code and poked it a few times with a REST client, sending different requests.
It seems to handle them, but I am on the same switch. Further testing is needed over greater distance.

Perehama:
I initialize it in the "for" loop.

Then it would be better coding style to use a "while".

Perehama:
I don't mind calling the loop each time there is a client.connected, but I do want to read the first line, the whole first line and nothing but the first line.

The ONLY reliable way to read an entire line is to continue checking available(), and reading the data until you SEE the line ending. Anything else WILL eventually fail.

Perehama:
I initialize it in the "for" loop.

The test is performed BEFORE the loop executes. If you don't initialize i in the for statement itself, there is NO guarantee the loop will execute even once, as the value of i is undefined. You are living on borrowed time...

Regards,
Ray L.

aarg:
Then it would be better coding style to use a "while".

That changes nothing. The condition is still evaluated BEFORE the loop ever executes.

Regards,
Ray L.

Perehama:
I initialize it in the “for” loop.

No, you don’t.

    for (int i; i <= maximumLength; i++) {
      char character = client.read();
      if (character == '\r') {
        serverBuffer[i] = '\0';
        break;
      }
      else {
        serverBuffer[i] = character;
        serverBuffer[i + 1] = '\0';
      }
    }

There is no assignment to i, it only gets used, compared and incremented.
A small change to your program and this for loop fails in any possible manner.

I could start with a value as low as -32678.

I never liked the way I had it written, although I am still unclear what more I needed to do to initialize i…

Anyhow, I rewrote it as follows, which is my 3rd iteration on it.

void webServer() {
  EthernetClient client = server.available();
  while (client.connected()) {
    int index;
    while (client.available() && index < serverBufferSize) {
      char character = client.read();
      if (character == '\r') {
        serverBuffer[index] = '\0';
        break;
      }
      else {
        serverBuffer[index++] = character;
        serverBuffer[index] = '\0';
      }
    }
// more code below to evaluate the buffer and send a response...

I think this addresses most of the concerns express, as well as my own.

Perehama:
I am still unclear what more I needed to do to initialize i…

You have to actually give it a value.

for (int i = 0; i <= maximumLength; i++) {

Assuming 0 is where you want i to start out. Without that it could have whatever random value happened to be left over in memory.

Same problem, index is not initialized, which means it can have any value.

You buffer is not long enough for any index, is it?

For some reason, I thought declaring a variable would initialize it at zero or NULL or false, etc., depending on the variable type...

Thank you for explaining this.

int index = 0;

Perehama:
For some reason, I thought declaring a variable would initialize it at zero or NULL or false, etc., depending on the variable type...

That is the case for global or static data.

Dynamic variables are a different beast.

Perehama:
I never liked the way I had it written, although I am still unclear what more I needed to do to initialize i…

Anyhow, I rewrote it as follows, which is my 3rd iteration on it.

void webServer() {

EthernetClient client = server.available();
  while (client.connected()) {
    int index;
    while (client.available() && index < serverBufferSize) {
      char character = client.read();
      if (character == ‘\r’) {
        serverBuffer[index] = ‘\0’;
        break;
      }
      else {
        serverBuffer[index++] = character;
        serverBuffer[index] = ‘\0’;
      }
    }
// more code below to evaluate the buffer and send a response…




I think this addresses most of the concerns express, as well as my own.

But now, if the client disconnects in the middle of a transmission, your code will simply hang…

Regards,
Ray L.

RayLivingston:
But now, if the client disconnects in the middle of a transmission, your code will simply hang…

Regards,
Ray L.

Please explain?
He is considered connected while data is available, and if no data than client.available() is also false.
What am I missing?

Perehama:
Please explain?
He is considered connected while data is available, and if no data than client.available() is also false.
What am I missing?

Connected is NOT a reliable indication that the connection is still alive. You can lose the connection, and connected() will still return true forever. You have to deal with that possibility.

Regards,
Ray L.

RayLivingston:
Connected is NOT a reliable indication that the connection is still alive. You can lose the connection, and connected() will still return true forever. You have to deal with that possibility.

Regards,
Ray L.

I do break the condition once I've sent a response. Thank you for the explanation.