Как надежно определить длину тела при закрытии соединения (RFC 2616 4.4.5)
Я не могу понять одну вещь прямо. RFC 2616 в 4.4.5 утверждает, что Message Length
можно определитьBy the server closing the connection.
".
Это подразумевает, что для сервера допустимо отвечать (например, возвращая большое изображение) ответом, который не имеет Content-Length
в заголовке, но клиент должен продолжать извлекать данные до тех пор, пока соединение не будет закрыто, а затем предположить, что все данные были загружены.
Но как клиент может точно знать, что соединение было намеренно закрыто сервером? Серверное приложение могло произойти сбой во время отправки данных, и ОС сервера, скорее всего, отправит FIN
пакет, чтобы изящно закрыть TCP соединение с клиентом.
1 ответ
Вы абсолютно правы, этот механизм абсолютно ненадежен. Это описано в RFC 7230:
Поскольку нет никакого способа отличить успешно завершенное сообщение с разделителями с разделителями от частично полученного сообщения, прерванного из-за сбоя в сети, сервер ДОЛЖЕН генерировать сообщения с кодированием или с разделителями по длине, когда это возможно. Функция близкого разграничения существует главным образом для обратной совместимости с HTTP/1.0.
К счастью, большая часть трафика HTTP сегодня - HTTP/1.1, с Content-Length или "Transfer-Encoding", чтобы явно определить конец сообщения.
Урок в том, что сообщение должно иметь свой собственный способ завершения; мы не можем повторно использовать EOF нижележащего транспортного уровня как EOF сообщения.
На этой ноте, (хорошо сформированный) html
документ или .gif
, .avi
и т.д., определяет свое собственное завершение; мы узнаем, получили ли мы неполный документ. Поэтому не так сложно передать его по HTTP / 1.0 без Content-Length.
Тем не менее, для простого текстового документа, javascript
, css
и т.д. EOF используется для обозначения конца документа, поэтому он проблематичен по HTTP/1.0.