daniel_pr
@daniel_pr

Bsd-socket. Почему бесконечное чтение при http запросе?

Дан код:

void read_data(int fd, char* buf, int buf_size) {
  int bytes_read = 0;
  while (true) {
    int bytes = read(fd, buf + bytes_read, buf_size - bytes_read);
    if (bytes == 0) break;
    bytes_read += bytes;
  }
}

При начальной итерации считываются все данные: голова запроса, заголовки, пейлоад; bytes, соотвественно, нулю не равен. При повторной итерации read, по идее, должен вернуть 0, так как все прочитано, но работа программы просто застывает на этом месте. Почему так?
  • Вопрос задан
  • 59 просмотров
Решения вопроса 1
jcmvbkbc
@jcmvbkbc
"I'm here to consult you" © Dogbert
При повторной итерации read, по идее, должен вернуть 0, так как все прочитано

Неа, не так это работает. 0 из read возвращается в одном единственном случае: если та сторона закрыла сокет на передачу и все посланные ею данные получены. В противном случае (сокет не закрыт) поведение зависит от настроек сокета: синхронный сокет при попытке чтения может заблокироваться в функции read или вернуть из неё -1 (и установить errno, например, в EINTR). Асинхронный сокет вернёт из read -1 и установит errno в EAGAIN или EWOULDBLOCK.
Ваш HTTP-сервер наверняка оставляет соединение открытым после того как прислал ответ на первый запрос, это можно понять по наличию заголовка Connection: Keep-Alive или отсутствию заголовка Connection: close в его ответе если это HTTP/1.1. Его можно попросить закрыть соединение после ответа, послав запрос с заголовком Connection: close или можно избежать блокировки в read прочитав только данные ответа размер которых прислан в заголовке ответа Content-Length.
Ответ написан
Пригласить эксперта
Ответы на вопрос 1
mayton2019
@mayton2019
Bigdata Engineer
Скорее всего отправитель перестал что-то отправлять. Это не ошибка. Это нормальное состояние сокета. Обрабатывайте на прикладном уровне содержимое потока. Если это http-response то там есть хедеры и длина и прочее и содержимое (XML/Json).
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы