Иногда данные, передающиеся с сервера, могут быть достаточно большими. И более того, мы можем не знать их конечный размер. Например, если нужно скачать архив или во время видео-трансляции.
Для решения этой проблемы можно загрузить данные полностью в оперативную память на сервере, вычислить Content-Length и осуществить передачу. После того, как контент будет целиком принят браузером, тот его моментально отобразит.
Существует еще одно решение, которое позволяет надежно передавать данные, когда мы не знаем их конечный размер. По ссылке находится пример изображения, которое отрисовывается постепенно по мере того, как происходит передача данных. Для этого используется механизм передачи небольшими частями, чанками (англ. chunks), и специальный заголовок Transfer-Encoding со значением chunked.
В стандартном ответе мы получаем все body целиком и после этого его обрабатываем. Мы не можем обрабатывать его частями потому, что тогда будем вводить какие-то свои уникальные правила внутри протокола. Но при передаче чанками мы можем обрабатывать ответ до полного получения body.
Сделаем запрос к сайту httpwatch.com:
telnet httpwatch.com 80
GET https://www.httpwatch.com/httpgallery/chunked/chunkedimage.aspx HTTP/1.1
Host: httpwatch.com
Connection: close
HTTP/1.1 200 OK
Cache-Control: no-cache, no-store
Pragma: no-cache
Trailer: X-HttpWatch-Sample
# вместо Content-Length здесь заголовок Transfer-Encoding
Transfer-Encoding: chunked
Content-Type: image/jpeg; charset=utf-8
Expires: -1
Server: Microsoft-IIS/10.0
X-AspNet-Version: 4.0.30319
X-Powered-By: ASP.NET
Arr-Disable-Session-Affinity: True
Date: Fri, 10 Jul 2020 09:18:05 GMT
400 # длина чанка
Какие-то данные первого чанка
400
Данные второго чанка
400
и так далее
0 # последний чанк нулевой длины
Обратите внимание, что заголовки как всегда отделяются от тела запроса переводом строки. В начале каждого чанка указывается его размер. За ним располагаются данные и в конце чанка делается перевод строки, затем идет следующий чанк и так далее. Таким образом можно передавать сколько угодно чанков, время ограничено только таймаутами внутри сервера.
Чтобы завершить передачу, нужно передать последний чанк, который должен быть нулевой длины. После него делается два перевода строки и запрос считается полностью переданным.
Формат сообщений
Для отделения записей размеров блоков (частей) от их содержания используется разделитель CRLF (как строка: «\r\n»; как байты в формате HEX: 0x0D, 0x0A). Длина блока — это размер содержания блока, разделители CRLF не учитываются.
Схематическое представление: <длина блока в HEX><CRLF><содержание блока><CRLF>
Последний блок строится по той же схеме, потому имеет следующий вид по причине отсутствия содержания: 0<CRLF><CRLF>
Стандарт также позволяет использовать в качестве разделителя только CR или только LF.
Дополнительные материалы
- Ссылка на изображение, передаваемое с помощью chunks (пример из видео)
- Chunked transfer encoding / Википедия
- Шестнадцатеричная система счисления (HEX) / Википедия

Остались вопросы? Задайте их в разделе «Обсуждение»
Вам ответят команда поддержки Хекслета или другие студенты
- Статья «Как учиться и справляться с негативными мыслями»
- Статья «Ловушки обучения»
- Статья «Сложные простые задачи по программированию»
- Урок «Как эффективно учиться на Хекслете»
- Вебинар «Как самостоятельно учиться»
Для полного доступа к курсу нужен базовый план
Базовый план откроет полный доступ ко всем курсам, упражнениям и урокам Хекслета, проектам и пожизненный доступ к теории пройденных уроков. Подписку можно отменить в любой момент.