Я наблюдаю в 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-клиентов.
FIN
сообщение клиентов, в то время как серверы его используют, кажется совершенно неправильным.RST
обрабатывается на уровне сокета, но FIN
не является?PS Я могу воспроизвести это с помощью HTTP-клиентов в Python 2/3, Java и httperf
утилита, написанная на C. Поэтому я считаю, что HTTP-клиенты часто игнорируют FIN
сообщение. Я хочу понять почему.