Передмова
Протокол HTTP — один із найважливіших протоколів в Інтернеті, хоча здається простим, але на практиці він часто стикається з проблемами, і ми стикалися з ним неодноразово. Існують довгі з'єднання та парсінг пакетів. Ви не можете нічого знати про протокол HTTP, потрібно добре його розуміти. Тож я написав цю серію, щоб поділитися проблемами та досвідом використання протоколу HTTP.
HTTP-протокол має заголовок і тіло як для пакетів запиту, так і для відповіді, а тіло — це ресурс, який ви хочете отримати, наприклад, html-сторінку, jpeg-зображення, і цей заголовок використовується для створення певних конвенцій. Наприклад, клієнт і сервер погоджуються щодо деяких форматів передачі, і клієнт спочатку отримує заголовок, знає деяку інформацію про формати, а потім починає читати основну частину.
Клієнт: Accept-Encoding:gzip (стисніть для мене, я використовую трафік, спочатку завантажуйте, а потім повільно розпакую)
Сервер 1: Content-Encoding: null (без заголовка Content-Encoding.) Я не даю стиснення, процесор не безкоштовний, хочете його?
Сервер 2: Content-Encoding:gzip (збереження трафіку, стиснення) Клієнт: Connection: keep-alive (Брате, ми нарешті побудували TCP-з'єднання, використаємо його наступного разу)
Сервер 1: З'єднання: підтримувати (не просто, продовжувати використовувати)
Сервер 2: З'єднання: закрито (Хто б не користувався ним разом із вами, наш TCP одноразовий, і наступного разу, коли знайдемо, доведеться знову підключитися) Протокол HTTP не має трьох рукостискань, і коли клієнт запитує ресурси у сервера, переважає сторона сервера. Є також деякі заголовки, які не мають процесу узгодження, але сервер безпосередньо повідомляє клієнту, що робити. Наприклад, довжина контенту вище — це те, що сервер повідомляє клієнту про розмір тіла. Але! Офіціант може не зможе заздалегідь точно сказати розмір тіла. Сервер має спочатку записати заголовок, а потім тіло, якщо ви хочете записати корпус у заголовку, потрібно заздалегідь знати розмір тіла. Якщо тіло динамічно генерується, сервер завершить роботу і почне записувати заголовок, що вимагає багато додаткових витрат, тому може не бути довжини контенту в заголовку.
То як клієнт знає розмір тіла? Сервер повідомляє це трьома способами.
1. Сервер уже знає розмір ресурсу і повідомляє через заголовок довжини контенту.
Content-Length:1076(body的大小是1076B,你读取1076B就可以完成任务了)
Transfer-Encoding: null
2. Сервер не може заздалегідь знати розмір ресурсу або не бажає витрачати ресурси на його обчислення заздалегідь, тому він додасть заголовок до http-повідомлення-відповіді під назвою Transfer-Encoding:chunked, що означає передачу блоків. Кожен блок має фіксований формат: розмір блоку спереду, дані позаду, а потім останній блок розміром 0. Таким чином, коли клієнт аналізує, йому потрібно звертати увагу на видалення деяких непотрібних полів.
Content-Length:null
Transfer-Encoding:chunked (接下来的body我要一块一块的传,每一块开始是这一块的大小,等我传到大小为0的块时,就没了)
3. Сервер не знає розміру ресурсу і не підтримує режим передачі з фрагментами, тому немає ні заголовка довжини контенту, ні заголовка кодування передачі. У цей момент заголовок, який повертає сервер, має бути близьким.
Content-Length:null
Transfer-Encoding:null
Connection:close(我不知道大小,我也用不了chunked,啥时候我关了tcp连接,就说明传输结束了)
|