Подобные проблемы обычно возникают, когда сервер закрывает соединение, пока клиент еще не прочитал данные. В вашем случае сервер закрывает соединение без чтения запроса от клиента. Но даже если вы прочитали полный запрос, проблема все равно может возникнуть, так как клиент мог отправить несколько запросов (конвейерная передача HTTP).
В стандарте HTTP даже есть рекомендация о том, как правильно выполнить закрытие и, в частности,решает проблему, которую вы получаете. Из RFC 7230, раздел 6.6 «Разрыв» :
Если сервер выполняет немедленное закрытие TCP-соединения, существует значительный риск того, что клиент не сможетпрочитать последний ответ HTTP. Если сервер получает дополнительные данные от клиента по полностью закрытому соединению, например, другой запрос, отправленный клиентом до получения ответа сервера, стек TCP сервера отправит клиенту пакет сброса ;к сожалению, пакет сброса может стереть неподтвержденные входные буферы клиента, прежде чем они будут прочитаны и интерпретированы синтаксическим анализатором HTTP клиента.
Чтобы избежать проблемы сброса TCP, серверы обычно закрывают соединение поэтапно . Во-первых, сервер выполняет половинное закрытие, закрывая только сторону записи соединения чтения / записи. Затем сервер продолжает чтение из соединения до тех пор, пока клиент не получит соответствующее закрытие , или пока сервер не будет достаточно уверен, что его собственный стек TCP получил подтверждение клиента пакета (пакетов), содержащегопоследний ответ сервера. Наконец, сервер полностью закрывает соединение.
Кроме того: настоятельно рекомендуется (СЛЕДУЕТ в стандарте) четко указывать размер тела либо с помощью заголовка Content-length
, либоиспользуя chunked Transfer Encoding - вместо того, чтобы просто закрывать соединение. Также настоятельно рекомендуется сообщить клиенту о том, что больше запросов не будет приниматься по этому соединению, добавив заголовок Connection: close
.
В целом: HTTP намного сложнее, чем можно подумать, просто взглянув нанесколько примеров. Существует стандарт , который описывает, как должны вести себя клиенты и сервер, и есть причина, по которой этот стандарт длинный. Тем не менее, пожалуйста, следуйте ему, если вы намерены реализовать свой собственный стек HTTP, а не просто использовать существующие реализации.