Can't reliably read a string from TCPServer

I’m writing a small code that reads from the network a percentage as a string, and converts in into a Particle Button LED ring value.

The problem I seem to have is during my tests, I use nc to send a value to my server, like this :

echo  "20"|nc -w 2 10.0.1.120 2000

It only works 1 time out of 3, apparently, and when it doesn’t work, nothing much is logged, it almost looks like the nc send is too fast and falls between two calls to loop().

Here is the code I use (animate() is called once for every loop)

void Percent::animate() {
    if (client.connected()) {
        readData();
    }
    else {
        client = server.available();
    }
    updateLeds();
}

void Percent::readData() {
    LOG_DEBUG(String::format("%s %i",__FUNCTION__,__LINE__));
    char data[4];
    int i=0;
    while (client.available()) {
        int c;
        for(i=0;i<4;i++) {
            int c = client.read();
            if (c==-1 || c==10)
                break;

            data[i] = c;
        }
    }
    if (i) {
        data[i] = 0;
        percent = String((char*)data).toInt();
        client.stop();
    }
}

Does that rings a bell to anyone?

You are sending 2 characters (20) - but looping to read 4???

Or am I missing somit

You’re missing the break, enclosed in a for loop.

In other words, I’m not sending 2 characters, I’m sending a carriage return \n as well :slight_smile: It is catch by :

if (c==-1 || c==10)

Basically after 4 characters or -1 or 10 it stops reading.

But if you are breaking out on 10 or reading a -1 while other bytes might not yet have arrived you’ll leave any potentially present bytes in the buffer which might carry over to the next read and influence that round.
You may need to allow for enough time for the whole lot to arrive and flush the buffer after you broke out (or don’t break and just read it all).

Also your client.stop() may have effects that carry over to the next read.

Maybe just purely log out your raw data without any extra logic to see what you actually receive from netcat and then build your logic around that.

Yes, for example, I suppose some client could send 20\n\r and I would be left with the \r hanging, but then it wouldn’t matter much because I’m closing the connection with stop().

Can you elaborate on the side effect of stop(), maybe that’s what my problem is.

My observations were that client = server.available(); didn’t even match (returned whatever it returns when there is no client available, nullptr maybe? I logged it as int and got some weird value.

You might have noticed, I’m no C++ expert so I must be doing some silly mistake!