Назад | Перейти на главную страницу

Несогласованность в управлении TCP и HTTP соединениями

Я наблюдаю в WireShark следующий сценарий:

Проблема, которую я вижу здесь, в том, что после получения [FIN, ACK] с сервера (4090) и подтверждая его (4092), http-клиент пытается отправить другой HTTP-запрос вместо того, чтобы немедленно закрыть (и, возможно, восстановить) TCP-соединение. Это выглядит как [FIN, ACK] просто игнорируется HTTP-клиентами.

Согласно RFC 7230 (6.3), протокол HTTP определяет механизм печи для постоянного управления подключением с использованием Connection заголовки. Он отлично работает, поскольку поддерживается как клиентами, так и серверами.

Однако HTTP обычно запускается поверх TCP. Управление TCP-соединением не имеет представления о протоколе сверху и может использоваться независимо от HTTP. Но HTTP-клиенты не поддерживают обработку этого (и, вероятно, не должны, это должно поддерживаться на уровне сокета). Однако серверы используют его, потому что он позволяет корректно закрыть соединение без отправки дополнительного HTTP-запроса. Например, nginx отправляет FIN пакет, когда соединение истекло или включено перезагрузка конфигурации.

ПРИМЕЧАНИЕ Когда HTTP-клиент получает RST с сервера закрывает соединение. И, похоже, это делается на уровне сокетов, поскольку я не могу найти ничего связанного с этим в исходном коде HTTP-клиентов.

  1. Правильно ли я понимаю ситуацию? Игнорирование FIN сообщение клиентов, в то время как серверы его используют, кажется совершенно неправильным.
  2. Зачем RST обрабатывается на уровне сокета, но FIN не является?
  3. Есть ли какой-нибудь RFC / другой стандарт о том, как HTTP-клиенты должны обрабатывать закрытие TCP-соединения?
  4. Это nginx делает что-то нестандартное или HTTP-клиенты не соответствуют стандарту?

PS Я могу воспроизвести это с помощью HTTP-клиентов в Python 2/3, Java и httperf утилита, написанная на C. Поэтому я считаю, что HTTP-клиенты часто игнорируют FIN сообщение. Я хочу понять почему.