send () и write () в выходной буфер TCP, который заполнен, не блокируется - PullRequest
0 голосов
/ 15 мая 2019

Я сталкиваюсь с проблемой простой функции (язык C ++), которая перебирает список объектов, сериализует их и отправляет на удаленный сервер.Я выполняю эту функцию на плате ESP32, которая работает с FreeRTOS и LwIP, поэтому у меня есть выходной буфер TCP, который по умолчанию ограничен 5744 байтами (я могу настроить его, но я не хочу использовать более 10-15 тысяч байтов).

По сути, это то, что происходит: я вызываю несколько раз (обычно 200-300 раз) write () или send () в сокете, каждый раз записывая ~ 1400 байт.Через некоторое время, если сервер на другой стороне немного медленный, я насыщаю выходной буфер TCP.Теперь, насколько я понимаю, send () или write () должны подождать, пока появится место для повторной записи данных в сокет, но вместо этого функция немедленно возвращает значение, отличное от значения, которое я хотела записать (скажем, 1400 байт).).

char buffer[1460];
result = write(current_socket, buffer, 1460);
if(result != 1460){
    // error
} else {
    // everything ok
}

Сокет является сокетом по умолчанию, поэтому он является блокирующим сокетом, и никакие параметры не были указаны.Я хотел бы, чтобы запись блокировалась, пока не будет достаточно места для записи всех 1460 байтов, указанных в коде выше.Единственной причиной, по которой запись должна вернуть ошибку, должен быть сбой на другой стороне, например, сервер закрывает сокет.Это возможно?

1 Ответ

2 голосов
/ 15 мая 2019

То, что вы видите, называется частичной записью .Это нормально для TCP.

Когда буфер частично заполнен, вызов write копирует столько данных, сколько поместится, и возвращает количество байтов, скопированных в буфер.Ваша задача - обработать оставшиеся данные позже.

Чтобы отправить буфер данных, необходимо выполнить цикл до тех пор, пока буфер не будет пуст:

buf_ptr = 0;
buf_end = 1460;
while(buf_ptr < buf_end) {
    rc = write(fd, buf + buf_ptr, buf_end - buf_ptr);
    if(rc <= 0)
        break
    buf_ptr += rc;
}
...