-2

I wrote a blocking loop to read unsolicited messages. I can't have an end char to detect the end of the message, but I am pretty happy with the timeout. VMIN=1 VTIME=5

Here when the recieved bytes are fewer than the buffer size, I presume the end of the messagge.

This code works, but will fail if the message is exactly 33 chars long. Any idea?

int l = 0;
string o = "";
char buf[33];

while(1) {
    if (l && l < 33) {
        // Messagge end, do something
    }
    l = read(fd, buf, 33);
    o.append(buf, 0, l);
}
Jackt
  • 171
  • 1
  • 1
  • 15
  • right, I explained better. No it cant be <= because thats the case of a piece of the stream. – Jackt Oct 07 '19 at 20:49
  • 1
    I think you actually need to create a [mcve] so it becomes clear what you want. Are all messages supposed to be multiples of exactly 33 `char`s (33, 66, 99, ...)? Do you ever clear `o` etc? – Ted Lyngmo Oct 08 '19 at 15:00

1 Answers1

0

VMIN should be set to 0. If VMIN > 0 the timer is not started until the first character arrives and the call can block indefinitely if the line is idle.

You also don't add your last buf to the string before you "do something". This should work better:

ssize_t l = 0; // use this type with read()
char buf[33];
std::string o;

while(true) {
    // VMIN == 0, VTIME > 0:
    // This is an overall timer, not an intercharacter one, so we need to loop to
    // emulate an intercharacter timer.

    while((l = read(fd, buf, 33)) > 0)
        o.append(buf, l); // this overload doesn't construct a temporary std::string

    if(o.size()) { 
        // do something with o

        o = ""; // reset o
    }

    if(l == -1) // read error
        break;
}
Ted Lyngmo
  • 93,841
  • 5
  • 60
  • 108
  • I do that in the former cycle. I never break. That doesnt fix the case of a message 33 chars long. – Jackt Oct 07 '19 at 21:12
  • @Jackt I just realized that changing VMIN requires a loop too and updated the answer accordingly. – Ted Lyngmo Oct 08 '19 at 07:01