Что происходит когда в браузере набираешь адрес и нажимаешь enter
Перейти к содержимому

Что происходит когда в браузере набираешь адрес и нажимаешь enter

  • автор:

Что происходит, когда вводишь url, или как работает интернет

Об этом спрашивают на собеседованиях. Структурированное понимание этого может помочь вам, даже если вы давно строите сложные архитектурные процессы или кодите 20-ый год подряд. Я — программист уже много лет, последние пару из которых пишу на Go в Каруне. Работа работой, а внутренний исследователь не дремлет. И вот я наконец-то решил привести в порядок информацию, разбросанную по разным закоулкам чертогов разума, по добротным книгам и статьям на тему сетевых технологий.

Хочу представить краткую выжимку о работе протоколов. А если тема окажется интересной, могу продолжить работать с ней более детально. Рассмотрим простейший пример: вы ввели некоторый url в адресную строку. Поехали.

The Open Systems Interconnection model (OSI)

Для начала придётся упомянуть семиуровневую модель OSI, с которой, возможно, каждый из вас знаком не понаслышке. Эталонная модель взаимодействия открытых систем является абстракцией, которая связывает и стандартизирует взаимодействие открытых систем. Она не описывает никакие используемые протоколы, а только определяет, какие функции выполняет каждый из её уровней. В основе любого сетевого взаимодействия лежит данная модель. Для привычного нам интернета схема OSI и соответствующие ей протоколы чаще всего имеют следующий вид:

Эталонная модель OSI и соответствие ей протоколов Интернета

Некоторые уровни могут отсутствовать и/или объединяться. Рассматривать работу схемы начнём с верхнего уровня — с того самого ввода адреса в адресную строку.

Прикладной уровень, HTTP

Прикладной уровень в модели OSI нужен для взаимодействия пользовательских приложений с сетью. Единица данных, которой оперирует прикладной уровень, называется сообщением. В описываемой системе уровень представлен протоколом HTTP. При вводе адреса google.com ваш браузер формирует HTTP сообщение, которое состоит из строки запроса, тела сообщения и заголовков со служебной информацией — такой как версия протокола, контрольная сумма сообщения, и т.д. Далее задача в том, чтобы передать HTTP-сообщение на следующий уровень — представления, если это HTTPS, или на TCP, если это HTTP.

Уровень представления, SSL (TLS)

Уровень представления отвечает за кодирование/декодирование, а также за шифрование/дешифрование данных. Благодаря этому уровню информация, передаваемая одной системой, всегда понятна другой системе.

Если сервер, к которому вы посылаете запрос, работает на протоколе HTTPS, то в него включён протокол защиты данных — SSL. SSL развивался до версии 3.0. Потом на основе него был создан TLS, который сейчас используется везде и гарантирует безопасность соединения. Принцип работы протокола базируется на ассиметричном шифровании и для создания безопасного канала связи оперирует такими понятиями как публичный ключ, приватный ключ, сеансовый ключ.

Ваш браузер и сервер заново создают защищённое соединение при каждом открытии сайта. Как же это работает? Для начала браузер создаёт запрос на запрашиваемый адрес, чтобы узнать есть ли у него SSL-сертификат. В ответ на запрос он получает информацию и публичный ключ, с полученной информацией делает запрос в центр сертификации (адреса центров сертификации уже есть в вашем браузере по умолчанию). Если информация подтверждается, ваш браузер генерирует сеансовый ключ, зашифровывает его публичным ключом и отправляет на сервер. Сервер расшифровывает сообщение с помощью приватного ключа и сохраняет сеансовый ключ. После этого соединение можно считать установленным — при общении клиента и сервера используется для шифрования сеансовый ключ. И «общение» между клиентом и сервером переходит на симметричное шифрование с помощью сгенерированного сеансового ключа.

Транспортный уровень, TCP

Транспортный уровень по определению обеспечивает передачу данных со степенью надёжности, которая требуется приложениям. В сети Интернет, в рассматриваемом взаимодействии, этот уровень представлен протоколом TCP, задача которого — надёжно доставить HTTP(S)-сообщение в пункт назначения. Единица данных как для TCP уровня, так и для следующего (IP) носит название пакет.

Операционная система, получив HTTP-сообщение от браузера, должна «встроить» его в пакет протокола нижележащего уровня — TCP. Такой процесс встраивания называется инкапсуляцией. Операция эта осуществляется на каждом уровне: пакеты вышележащего уровня инкапсулируются в пакеты нижележащего. И на самом нижнем уровне мы получаем информационную “матрёшку” с вложенными друг в друга пакетами, со служебной информацией в виде заголовков, добавленных на каждом уровне:

Формируются TCP-пакеты чаще всего в ядре операционной системы. Вся прелесть протокола TCP — в надёжности доставки. Использование этого протокола предусматривает установление так называемого логического соединения между двумя конечными узлами сети (перед этим, естественно, такое соединение нужно согласовать). Надёжную доставку пакетов протокол TCP обеспечивает посредством нумерации пакетов, подтверждения их передачи квитанциями, а также контроля правильного порядка пакетов. Схема установления логического соединения, передачи данных и разрыва соединения представлена на рисунке ниже:

Работа хостов с помощью логического соединения

Сетевой уровень, IP

Сетевой уровень в общем случае нужен для образования единой транспортной системы, которая объединяет несколько сетей. Сети, кстати, могут иметь разные стеки протоколов. Также на этом уровне определяется маршрут пересылки пакетов от отправителя к получателю.

По ходу перемещения IP-пакета по сети маршрутизаторы передают пакеты от одной сети к другой или же на конечный узел-получатель. Данный протокол не занимается установлением соединения, не контролирует целостность данных, не гарантирует доставку и не отвечает за их достоверность, то есть реализует политику доставки «по возможности». Всё это бремя возложено на вышележащий протокол — TCP. Получив TCP-пакет, ОС инкапсулирует его в IP-пакет, добавляет в него свои параметры и передаёт далее.

DNS

Для того чтобы отправить какие-то данные серверу в IP-пакете, нужно узнать его IP-адрес. Для этого есть специальный протокол DNS, с помощью которого делается отдельный от основного запрос. Запрос этот называется DNS-запросом, и посылается он на специальный DNS сервер — его адрес заведомо известен и прописал в настройках вашей операционной системы. DNS-протокол — это представитель протокола прикладного уровня. Кратко его работу можно описать так:

  1. Клиент создает DNS-сообщение, добавляя неизвестный URL в раздел вопроса этого сообщения.
  2. Сообщение DNS инкапсулируется в UDP-дейтаграмму протокола UDP транспортного уровня.
  3. UDP-дейтаграмма инкапсулируется в IP-пакет данных с IP-адресом назначения DNS-сервера и отправляется на DNS-сервер.
  4. DNS-сервер возвращает запись ресурса, в которой указан IP-адрес URL.

Строго говоря, запрос этот выполняется не всегда. Так как вначале браузер проверяет соответствие IP адреса и домена в своем кэше (для chrome это chrome://net-internals/#dns). Затем, если соответствия не найдено, браузер обращается к операционной системе, которая ищет информацию в системном файле hosts. И только в случае, если ничего не найдено в этом файле, посылается запрос DNS. Полученный адрес уже можно указать в формируемом IP-пакете основного запроса.

Физический и канальный уровни, Ethernet

Канальный уровень (также — уровень передачи данных) необходим для передачи сырых данных физического уровня по надежной линии связи. Основная задача на этом уровне — обнаружение и коррекция ошибок. Также он может исправлять ошибки за счёт повторной передачи поврежденных кадров. Канальный уровень тоже должен проверить доступность среды — можно ли выполнять пересылку данных в конкретный момент. Иногда эту функцию выделяют в отдельный подуровень управления доступом к среде (MAC).

Физический уровень отвечает за передачу потока битов по каналам физической связи (коаксиальные кабеля, оптоволокно, витая пара). Со стороны компьютера функции физического уровня выполняет сетевой адаптер или COM-порт. На этом уровне есть только поток битов и ничего более: протокол «не задумывается» об информации, которую он передаёт.

В нашем случае протокол Ethernet объединяет эти два уровня. Ethernet оперирует единицей данных, которая называется кадр. Для физического уровня нет никакого анализа информации, которая передаётся. Для передачи данных между узлами протокол работает по схеме с коммутацией пакетов, то есть сеть ведёт себя менее «ответственно», не создавая для абонентов отдельных каналов связи. Данные могут задерживаться и даже теряться. Поэтому ошибки на этом уровне не исправляются. Это опять же возложено на протокол верхнего уровня — TCP.

Для физического уровня Ethernet описывается стандартом группы IEEE 802.3, который определяет физические характеристики канала связи. Например, какой кабель будет использоваться для передачи данных: витая пара, коаксиальный кабель или оптоволокно. Тут же определяется вид кодирования и модуляции сигнала. Технические характеристики каждого стандарта хорошо описаны в данной статье. Например, спецификация 100Base-T определяет в качестве используемого кабеля витую пару, с максимальной длинной физического сегмента 100 метров и манчестерским кодом для данных в кабеле.

Путь пакета

На следующей схеме представлена схема взаимодействия узлов сети. Наш пакет выходит из конечного узла слева, проходя через концентраторы, коммутаторы (работающие на канальном уровне) и маршрутизаторы, работающие на сетевом уровне:

Общая схема взаимодействия узлов сети

Как видно из схемы, концентратор работает с данными на физическом уровне, но в настоящее время они вытеснены сетевыми коммутаторами, умеющими работать на канальном и физическом уровнях.

Совершив путь от одного конечного узла до другого, он распаковывается в обратном порядке: из Ethernet-кадра вытаскивается IP-пакет, из него, в свою очередь, TCP-пакет. Получив в конечном счёте HTTP-сообщение и считав с него нужную информацию, сервер формирует и посылает ответное HTTP-сообщение. Оно, в свою очередь, также проходит через каждый уровень и возвращается в виде ответа клиенту, распаковывается каждым уровнем, и мы видим заветную информацию на экране.

Конечно, это краткий обзор того, что происходит в сети Интернет на примере HTTP-запроса. Существует много деталей, которые не вошли в эту статью, дабы не растягивать её до бесконечности, но, надеюсь, войдут в будущие мои обзоры.

Книги, которые помогли мне. Рекомендую и вам:

  1. Олифер В.Г., Олифер Н.А. Компьютерные сети. Принципы, технологии, протоколы — СПб.: Питер, 2018. — 992
  2. Таненбаум Э., Уэзеролл Д. Компьютерные сет — СПб.: Питер, 2020. — 960 с.: ил.

Что на самом деле происходит, когда пользователь вбивает в браузер адрес google.com

Эта статья является попыткой ответа на старый вопрос для собеседований: «Что же случается, когда вы печатаете в адресной строке google.com и нажимаете Enter?» Мы попробуем разобраться в этом максимально подробно, не пропуская ни одной детали.

Примечание: публикация основана на содержании репозитория What happens when.

Представленный контент изобилует большим количеством терминов, в переводе некоторых из них могут присутствовать различные неточности. Если вы обнаружите какую-то ошибку в нашем переводе — напишите личным сообщением, и мы всё исправим.

Мы перенесли перевод в репозиторий GitHub и отправили Pull Request автору материала — оставляйте свои правки к тексту, и вместе мы сможем значительно улучшить его.

1. Нажата клавиша «g»

Далее в статье содержится информация о работе физической клавиатуры и прерывания операционной системы. Но много чего происходит и помимо этого — когда вы нажимаете клавишу «g», браузер получает событие и запускается механизм автоподстановки. В зависимости от алгоритма браузера и его режима (включена ли функция «инкогнито») в выпадающем окне под строкой URL пользователю будет предложено определённое количество вариантов для автоподстановки.

Большинство алгоритмов автоподстановки ранжируют рекомендации в зависимости от истории поиска и оставленных закладках. Некоторые браузеры (например, Rockmelt) даже предлагают профили друзей на Facebook. Когда пользователь планирует напечатать в адресной строке «google.com», ничего из вышеперечисленного не играет роли, но тем не менее выполнится большое количество кода, а рекомендации будут обновляться с каждой новой напечатанной буквой. Возможно, браузер предложит перейти на google.com, до того, как пользователь вобьёт адрес целиком.

2. Клавиша «enter» нажата до конца

В качестве некой нулевой точки можно выбрать момент, когда клавиша Enter на клавиатуре нажата до конца и находится в нижнем положении. В этой точке замыкается электрическая цепь этой клавиши и небольшое количество тока отправляется по электросхеме клавиатуры, которая сканирует состояние каждого переключателя клавиши и конвертирует сигнал в целочисленный код клавиши (в данном случае — 13). Затем контроллер клавиатуры конвертирует код клавиши для передачи его компьютеру. Как правило, сейчас передача происходит через USB или Bluetooth, а раньше клавиатура подключалась к компьютеру с помощью коннекторов PS/2 или ADB.

В случае USB-клавиатуры:

  • Для работы USB-контуру клавиатуры требуется 5 вольт питания, которые поступают через USB-контроллер на компьютере.
  • Сгенерированный код клавиши хранится в регистре внутренней памяти клавиатуры, который называется «конечной точкой» (endpoint).
  • USB-контроллер компьютера опрашивает эту конечную точку каждые 10 микросекунд и получает хранящийся там код клавиши.
  • Затем это значение поступает в USB SIE (Serial Interface Engine) для конвертации в один или более USB-пакетов, которые формируются по низкоуровневому протоколу USB.
  • Эти пакеты затем пересылаются с помощью различных электрических сигналов через D+ и D- контакты с максимальной скоростью 1,5 Мб/сек — поскольку HID-устройства (Human Interface Device) всегда были «низкоскоростными».
  • Этот последовательный сигнал далее декодируется в USB-контроллере компьютера и интерпретируется универсальным драйвером HID-устройства (клавиатуры). Затем значение кода клавиши передаётся на «железный» уровень абстракции операционной системы.
  • Когда пользователь прикладывает палец к современному ёмкостному тач-экрану, небольшое количество тока передаётся к пальцу. Это замыкает цепь через электростатическое поле проводящего слоя и создаёт падение напряжения в этой точке экрана. Экранный контроллер затем инициирует прерывание, сообщающее координату «клика».
  • Затем мобильная ОС оповещает текущее открытое приложение о событии клика в одном из GUI-элементов (в этом случае — кнопках виртуальной клавиатуры).
  • Виртуальная клавиатура вызывает программное прерывание для отправки сообщения «клавиша нажата» обратно в ОС.
  • Это прерывание оповещает текущее открытое приложение о возникновении события «нажатия клавиши».
2.1 Возникло прерывание [не для USB-клавиатур]

Клавиатура отправляет сигналы в свою «линию запросов прерываний» (IRQ), которая затем сопоставляется с «вектором прерывания» (целое число) контроллером прерываний. Процессор использует «таблицу дескрипторов прерываний» (IDT) для сопоставления векторов прерываний с функциями («обработчики прерываний») ядра. Когда появляется прерывание, процессор (CPU) обновляет IDT вектором прерывания и запускает соответствующий обработчик. Таким образом, в дело вступает ядро.

2.2 (На Windows) Сообщение WM_KEYDOWN отправлено приложению

HID передаёт событие нажатой клавиши драйверу KBDHID.sys , который конвертирует его в скан-код (scancode). В данном конкретном случае скан-код — VK_RETURN ( 0x0D ). Драйвер KDBHID.sys связывается с драйвером KBDCLASS.sys (драйвер классов клавиатуры). Он отвечает за безопасную обработку всего ввода с клавиатуры. В дальнейшем этот драйвер вызывает Win32K.sys (после возможной передачи сообщения через установленные сторонние клавиатурные фильтры). Все это происходит в режиме ядра.

Win32K.sys определяет, какое окно активно в данный момент, с помощью функции GetForegroundWindow() . Этот API обеспечивает обработку окна адресной строки в браузере. Затем главный «насос сообщений» Windows вызывает SendMessage(hWnd, WM_KEYDOWN, VK_RETURN, lParam) . lParam — это битовая маска, которая указывает на дальнейшую информацию о нажатии клавиши: счётчик повторов (в этом случае 0), актуальный скан-код (может зависеть от OEM, но VK_RETURN обычно не зависит от этого), информацию о том, были ли нажаты дополнительные клавиши (например, Alt, Shift, Ctrl — в нашем случае не были) и некоторые другие данные.

В API Windows есть функция SendMessage , которая помещает сообщение в очередь для конкретного обработчика окон ( hWnd ). После этого для обработки всех сообщений очереди вызывается главная функция обработки сообщений ( WindowProc ), присвоенная обработчику hWnd .

Окно ( hWnd ), активное в данный момент, представляет из себя контрол обработки и в этом случае у WindowsProc есть обработчик для сообщений WM_KEYDOWN . Этот код изучает третий параметр, который поступил в SendMessage (wParam) и, поскольку это VK_RETURN , понимает, что пользователь нажал клавишу ENTER.

2.3 (В OS X) Событие NSEVent KeyDown отправлено приложению

Сигнал прерывания активирует событие прерывания в драйвере I/O Kit клавиатуры. Драйвер переводит сигнал в код клавиатуры, который затем передаётся процессу OS X под названием WindowServer . В результате, WindowsServer передаёт событие любому подходящему (активному или «слушающему») приложению через Mach-порт, в котором событие помещается в очередь. Затем события могут быть прочитаны из этой очереди потоками с достаточными привилегиями, чтобы вызывать функцию mach_ipc_dispatch . Чаще всего это происходит и обрабатывается с помощью основного цикла NSApplication через NSEvent в NSEventype KeyDown .

2.4 (В GNU/Linux) Сервер Xorg слушает клавиатурные коды

В случае графического X server, для получения нажатия клавиши будет использован общий драйвер событий evdev . Переназначение клавиатурных кодов скан-кодам осуществляется с помощью специальных правил и карт X Server. Когда маппинг скан-кода нажатой клавиши завершён, X server посылает символ в window manager (DWM, metacity, i3), который затем отправляет его в активное окно. Графический API окна, получившего символ, печатает соответствующий символ шрифта в нужном поле.

3. Парсинг URL

Теперь у браузера есть следующая информация об URL:

Protocol «HTTP»
Использовать «Hyper Text Transfer Protocol»

Resource «/»
Показать главную (индексную) страницу

3.1 Это URL или поисковый запрос?

Когда пользователь не вводит протокол или доменное имя, то браузер «скармливает» то, что человек напечатал, поисковой машине, установленной по умолчанию. Часто к URL добавляется специальный текст, который позволяет поисковой машине понять, что информация передана из URL-строки определённого браузера.

3.2 Список проверки HSTS
  • Браузер проверяет список «предзагруженных HSTS (HTTP Strict Transport Security)». Это список сайтов, которые требуют, чтобы к ним обращались только по HTTPS.
  • Если нужный сайт есть в этом списке, то браузер отправляет ему запрос через HTTPS вместо HTTP. В противном случае, начальный запрос посылается по HTTP. (При этом сайт может использовать политику HSTS, но не находиться в списке HSTS — в таком случае на первый запрос по HTTP будет отправлен ответ о том, что необходимо отправлять запросы по HTTPS. Однако это может сделать пользователя уязвимым к downgrade-атакам — чтобы этого избежать, в браузеры и включают список HSTS).
3.3 Конвертация не-ASCII Unicode символов в название хоста
  • Браузер проверяет имя хоста на наличие символов, отличных от a-z , A-Z , 0-9 , — , или . .
  • В случае доменного имени google.com никаких проблем не будет, но если бы домен содержал не-ASCII символы, то браузер бы применил кодировку Punycode для этой части URL.

4. Определение DNS

  • Браузер проверяет наличие домена в своём кэше.
  • Если домена там нет, то браузер вызывает библиотечную функцию gethostbyname (отличается в разных ОС) для поиска нужного адреса.
  • Прежде, чем искать домен по DNS gethostbyname пытается найти нужный адрес в файле hosts (его расположение отличается в разных ОС).
  • Если домен нигде не закэширован и отсутствует в файле hosts , gethostbyname отправляет запрос к сетевому DNS-серверу. Как правило, это локальный роутер или DNS-сервер интернет-провайдера.
  • Если DNS-сервер находится в той же подсети, то ARP-запрос отправляется этому серверу.
  • Если DNS-сервер находится в другой подсети, то ARP-запрос отправляется на IP-адрес шлюза по умолчанию (default gateway).
4.1 Процесс отправки ARP-запроса

Для того, чтобы отправить широковещательный ARP-запрос необходимо отыскать целевой IP-адрес, а также знать MAC-адрес интерфейса, который будет использоваться для отправки ARP-запроса.

Кэш ARP проверяется для каждого целевого IP-адреса — если адрес есть в кэше, то библиотечная функция возвращает результат: Target IP = MAC .

Если же записи в кэше нет:

  • Проверяется таблица маршрутизации — это делается для того, чтобы узнать, есть ли искомый IP-адрес в какой-либо из подсетей локальной таблицы. Если он там, то запрос посылается с помощью интерфейса, связанного с этой подсетью. Если адрес в таблице не обнаружен, то используется интерфейс подсети шлюза по умолчанию.
  • Определяется MAC-адрес выбранного сетевого интерфейса.
  • Отправляется ARP-запрос (второй уровень стека):

Sender MAC: interface:mac:address:here
Sender IP: interface.ip.goes.here
Target MAC: FF:FF:FF:FF:FF:FF (Broadcast)
Target IP: target.ip.goes.here

В зависимости от того, какое «железо» расположено между компьютером и роутером (маршрутизатором):

  • Если компьютер напрямую подключён к роутеру, то это устройство отправляет ARP-ответ (ARP Reply).
  • Если компьютер подключён к сетевому концентратору, то этот хаб отправляет широковещательный ARP-запрос со всех своих портов. Если роутер подключён по тому же «проводу», то отправит ARP-ответ.
  • Если компьютер соединён с сетевым коммутатором, то этот свитч проверит локальную CAM/MAC-таблицу, чтобы узнать, какой порт в ней имеет нужный MAC-адрес. Если нужного адреса в таблице нет, то он заново отправит широковещательный ARP-запрос по всем портам.
  • Если в таблице есть нужная запись, то свитч отправит ARP-запрос на порт с искомым MAC-адресом.
  • Если роутер «на одной линии» со свитчем, то он ответит (ARP Reply).

Sender MAC: target:mac:address:here
Sender IP: target.ip.goes.here
Target MAC: interface:mac:address:here
Target IP: interface.ip.goes.here

Теперь у сетевой библиотеки есть IP-адрес либо DNS-сервера либо шлюза по умолчанию, который можно использовать для разрешения доменного имени:

  • Порт 53 открывается для отправки UDP-запроса к DNS-серверу (если размер ответа слишком велик, будет использован TCP).
  • Если локальный или на стороне провайдера DNS-сервер «не знает» нужный адрес, то запрашивается рекурсивный поиск, который проходит по списку вышестоящих DNS-серверов, пока не будет найдена SOA-запись, а затем возвращается результат.

5. Открытие сокета

Когда браузер получает IP-адрес конечного сервера, то он берёт эту информацию и данные об используемом порте из URL (80 порт для HTTP, 443 для HTTPS) и осуществляет вызов функции socket системной библиотеки и запрашивает поток TCP сокета — AF_INET и SOCK_STREAM .

  • Этот запрос сначала проходит через транспортный уровень, где собирается TCP-сегмент. В заголовок добавляется порт назначения, исходный порт выбирается из динамического пула ядра ( ip_local_port_range в Linux).
  • Получившийся сегмент отправляется на сетевой уровень, на котором добавляется дополнительный IP-заголовок. Также включаются IP-адрес сервера назначения и адрес текущей машины — после этого пакет сформирован.
  • Пакет передаётся на канальный уровень. Добавляется заголовок кадра, включающий MAC-адрес сетевой карты (NIC) компьютера, а также MAC-адрес шлюза (локального роутера). Как и на предыдущих этапах, если ядру ничего не известно о MAC-адресе шлюза, то для его нахождения отправляется широковещательный ARP-запрос.
  • Ethernet
  • WiFi
  • По сотовой связи

В конечном итоге пакет доберётся до маршрутизатора, управляющего локальной подсетью. Затем он продолжит путешествовать от одного роутера к другому, пока не доберётся до сервера назначения. Каждый маршрутизатор на пути будет извлекать адрес назначения из IP-заголовка и отправлять пакет на следующий хоп. Значение поля TTL (time to live) в IP-заголовке будет каждый раз уменьшаться после прохождения каждого роутера. Если значение поля TTL достигнет нуля, пакет будет отброшен (это произойдёт также если у маршрутизатора не будет места в текущей очереди — например, из-за перегрузки сети).

Во время TCP-соединения происходит множество подобных запросов и ответов.

5.1 Жизненный цикл TCP-соединения

a. Клиент выбирает номер начальной последовательности (ISN) и отправляет пакет серверу с установленным битом SYN для открытия соединения.

b. Сервер получает пакет с битом SYN и, если готов к установлению соединения, то:

  • Выбирает собственный номер начальной последовательности;
  • Устанавливает SYN-бит, чтобы сообщить о выборе начальной последовательности;
  • Копирует ISN клиента +1 в поле ACK и добавляет ACK-флаг для обозначения подтверждения получения первого пакета.
  • Увеличивает номер своей начальной последовательности;
  • Увеличивает номер подтверждения получения;
  • Устанавливает поле ACK.
  • Когда одна сторона отправляет N байтов, то увеличивает значение поля SEQ на это число.
  • Когда вторая сторона подтверждает получение этого пакета (или цепочки пакетов), она отправляет пакет ACK, в котором значение поля ACK равняется последней полученной последовательности.
  • Сторона, которая хочет закрыть соединение, отправляет пакет FIN;
  • Другая сторона подтверждает FIN (с помощью ACK) и отправляет собственный FIN-пакет;
  • Инициатор прекращения соединения подтверждает получение FIN отправкой собственного ACK.

6. TLS handshake

  • Клиентский компьютер отправляет сообщение ClientHello серверу со своей версией протокола TLS, списком поддерживаемых алгоритмов шифрования и методов компрессии данных.
  • Сервер отвечает клиенту сообщением ServerHello , содержащим версию TLS, выбранный метод шифрования, выбранные методы компрессии и публичный сертификат сервиса, подписанный центром сертификации. Сертификат содержит публичный ключ, который будет использоваться клиентом для шифрования оставшейся части процедуры «рукопожатия» ( handshake ), пока не будет согласован симметричный ключ.
  • Клиент подтверждает сертификат сервера с помощью своего списка центров сертификации. Если сертификат подписан центром из списка, то серверу можно доверять, и клиент генерирует строку псевдослучайных байтов и шифрует её с помощью публичного ключа сервера. Эти случайные байты могут быть использованы для определения симметричного ключа.
  • Сервер расшифровывает случайные байты с помощью своего секретного ключа и использует эти байты для генерации своей копии симметричного мастер-ключа.
  • Клиент отправляет серверу сообщение Finished , шифруя хеш передачи с помощью симметричного ключа.
  • Сервер генерирует собственный хеш, а затем расшифровывает полученный от клиента хеш, чтобы проверить, совпадёт ли он с собственным. Если совпадение обнаружено, сервер отправляет клиенту собственный ответ Finished , также зашифрованный симметричным ключом.
  • После этого TLS-сессия передаёт данные приложения (HTTP), зашифрованные с помощью подтверждённого симметричного ключа.

7. Протокол HTTP

Если используемый браузер был создан Google, то вместо отправки HTTP-запроса для получения страницы, он отправит запрос, чтобы попытаться «договориться» с сервером об «апгрейде» протокола с HTTP до SPDY («спиди»).

Если клиент использует HTTP-протокол и не поддерживает SPDY, то отправляет серверу запрос следующей формы:

GET / HTTP/1.1
Host: google.com
Connection: close
[другие заголовки]

где [другие заголовки] — это серия пар «ключ: значение», разбитых переносом строки. (Здесь предполагается, что в использованном браузере нет никаких ошибок, нарушающих спецификацию HTTP. Также предполагается, что браузер использует HTTP/1.1 , в противном случае он может не включать заголовок Host в запрос и версия, отданная в ответ на GET-запрос может быть HTTP/1.0 или HTTP/0.9 ).

HTTP/1.1 определяет опцию закрытия соединения («close») для отправителя — с её помощью происходит уведомление о закрытии соединения после завершения ответа. К примеру:

Connection: close

Приложения HTTP/1.1 , которые не поддерживают постоянные соединения, обязаны включать опцию «close» в каждое сообщение.

После отправки запроса и заголовков, браузер отправляет серверу единичную пустую строку, сигнализируя о том, что содержимое сообщения закончилось.

Сервер отвечает специальным кодом, который обозначает статус запроса и включает ответ следующей формы:

200 OK
[заголовки ответа]

После этого посылается пустая строка, а затем оставшийся контент HTML-страницы www.google.com. Сервер может затем закрыть соединение, или, если того требуют отправленные клиентом заголовки, сохранять соединение открытым для его использования следующими запросами.

Если HTTP-заголовки отправленные веб-браузером включают информацию, которой серверу достаточно для определения версии файла, закэшированного в браузере и этот файл не менялся со времени последнего запроса, то ответ может принять следующую форму:

304 Not Modified
[заголовки ответа]

и, соответственно, клиенту не посылается никакого контента, вместо этого браузер «достаёт» HTML из кэша.

После разбора HTML, браузер (и сервер) повторяет процесс загрузки для каждого ресурса (изображения, стили, скрипты, favicon.ico и так далее), на который ссылается HTML-страница, но при этом изменяется адрес каждого запроса c GET / HTTP/1.1 на GET /$(относительный URL ресурса www.google.com) HTTP/1.1 .

Если HTML ссылается на ресурс, размещённый на домене, отличном от google.com, то браузер возвращается к шагам, включающим разрешение доменного имени, а затем заново проходит процесс до текущего состояния, но уже для другого домена. Заголовок Host в запросе вместо google.com будет установлен на нужное доменное имя.

7.1 Обработка HTTP-запросов на сервере

HTTPD (HTTP Daemon) является одним из инструментов обработки запросов/ответов на стороне сервера. Наиболее популярные HTTPD-серверы это Apache или Nginx для Linux и IIS для Windows.

— HTTPD (HTTP Daemon) получает запрос.

— Сервер разбирает запрос по следующим параметрам:

  • Метод HTTP-запроса ( GET , POST , HEAD , PUT или DELETE ). В случае URL-адреса, который пользователь напечатал в строке браузера, мы имеем дело с GET-запросом.
  • Домен. В нашем случае — google.com.
  • Запрашиваемые пути/страницы, в нашем случае — / (нет запрошенных путей, / — это путь по умолчанию).

— Сервер проверяет, что google.com может принимать GET-запросы.

— Сервер проверяет, имеет ли клиент право использовать этот метод (на основе IP-адреса, аутентификации и прочее).

— Если на сервере установлен модуль перезаписи ( mod_rewrite для Apache или URL Rewrite для IIS), то он сопоставляет запрос с одним из сконфигурированных правил. Если находится совпадающее правило, то сервер использует его, чтобы переписать запрос.

— Сервер находит контент, который соответствует запросу, в нашем случае он изучит индексный файл.

— Далее сервер разбирает («парсит») файл с помощью обработчика. Если Google работает на PHP, то сервер использует PHP для интерпретации индексного файла и направляет результат клиенту.

8. За кулисами браузера

Задача браузера заключается в том, чтобы показывать пользователю выбранные им веб-ресурсы, запрашивая их с сервера и отображая в окне просмотра. Как правило такими ресурсами являются HTML-документы, но это может быть и PDF, изображения или контент другого типа. Расположение ресурсов определяется с помощью URL.

Способ, который браузер использует для интерпретации и отображения HTML-файлов описан в спецификациях HTML и CSS. Эти документы разработаны и поддерживаются консорциумом W3C (World Wide Wib Consortium), которая занимается стандартизацией веба.

Интерфейсы браузеров сильно похожи между собой. У них есть большое количество одинаковых элементов:

  • Адресная строка, куда вставляются URL-адреса;
  • Кнопки возврата на предыдущую и следующую страницу;
  • Возможность создания закладок;
  • Кнопки обновления страницы (рефреш) и остановки загрузки текущих документов;
  • Кнопка «домой», возвращающая пользователя на домашнюю страницу.
Высокоуровневая структура браузера

Браузер включает следующие компоненты:

  • Пользовательский интерфейс: В него входит адресная строка, кнопки продвижения вперёд/назад, меню закладок и так далее. Сюда относятся все элементы, кроме окна, в котором собственно отображается веб-страница.
  • «Движок» браузера: Распределяет действия между движком рендеринга и интерфейсом пользователя.
  • «Движок» рендеринга: Отвечает за отображение запрашиваемого контента. К примеру, если запрашивается HTML, то «движок» разбирает код HTML и CSS, а затем отображает полученный контент на экране.
  • Сетевая часть: с помощью сетевых функций браузер обрабатывает вызовы, вроде HTTP-запросов, с применением различных реализаций для разных платформ.
  • Бэкенд интерфейса (UI): Используется для отрисовки базовых виджетов, вроде комбо-боксов и окон.
  • Интерпретатор JavaScript: Используется для парсинга и выполнения JavaScript-кода.
  • Хранилище данных: Браузеру может понадобиться локально хранить некоторые данные (например, cookie). Кроме того, браузеры поддерживают различные механизмы хранения, такие как localStorage , IndexedDB , WebSQL и FileSystem .

9. Парсинг HTML

Движок рендеринга начинает получать содержимое запрашиваемого документа от сетевого механизма браузера. Как правило, контент поступает кусками по 8Кб. Главной задачей HTML-парсера является разбор разметки в специальное дерево.

Получающееся на выходе дерево («parse tree») — это дерево DOM-элементов и узлов атрибутов. DOM — сокращение от Document Object Model . Это модель объектного представления HTML-документа и интерфейс для взаимодействия HTML-элементов с «внешним миром» (например, JavaScript-кодом). Корнем дерева является объект «Документ».

Алгоритм разбора

HTML-нельзя «распарсить» с помощью обычных анализаторов (нисходящих или восходящих). Тому есть несколько причин:

  • Прощающая почти что угодно природа языка;
  • Тот факт, что браузеры обладают известной толерантностью к ошибкам и поддерживают популярные ошибки в HTML.
  • Процесс парсинга может заходить в тупик. В других языках код, который требуется разобрать, не меняется в процессе анализа, в то время как в HTML с помощью динамического кода (например, скриптовые элементы, содержащие вызовы document.write() ) могут добавляться дополнительные токены, в результате чего сам процесс парсинга модифицирует вывод.

Алгоритм состоит из двух этапов: токенизации и создания дерева.

Действия после завершения парсинга

После этого браузер начинает подгружать внешние ресурсы, связанные со страницей (стили, изображения, скрипты и так далее).

На этом этапе браузер помечает документ, как интерактивный и начинает разбирать скрипты, находящиеся в «отложенном» состоянии: то есть те из них, что должны быть исполнены после парсинга. После этого статус документа устанавливается в состояние « complete » и инициируется событие загрузки (« load »).

Важный момент: ошибки «Invalid Syntax» при разборе не может быть, поскольку браузеры исправляют любой «невалидный» контент и продолжают работу.

10. Интерпретация CSS

  • Во время разбора браузер парсит CSS-файлы, содержимое тегов и атрибутов «style» c помощью «лексической и синтаксической грамматики CSS».
  • Каждый CSS-файл разбирается в объект StyleSheet , каждый из таких объектов содержит правила CSS с селекторами и объектами в соответствии с грамматикой CSS.
  • Парсер CSS может быть как восходящим, так и нисходящим.

11. Рендеринг страниц

  • Путём перебора DOM-узлов и вычисления для каждого узла значений CSS-стилей создаётся «Дерево рендера» (Render Tree или Frame Tree).
  • Вычисляется предпочтительная ширина каждого узла в нижней части дерева — для этого суммируются значения предпочтительной ширины дочерних узлов, а также горизонтальные поля, границы и отступы узлов.
  • Вычисляется реальная ширина каждого узла сверху-вниз (доступная ширина каждого узла выделяется его потомкам).
  • Вычисляется высота каждого узла снизу-вверх — для этого применяется перенос текста и суммируются значения полей, высоты, отступов и границ потомков.
  • Вычисляются координаты каждого узла (с использованием ранее полученной информации).
  • Если элементы плавающие или спозиционированы абсолютно или относительно, предпринимаются более сложные действия. Более подробно они описаны здесь и здесь.
  • Создаются слои для описания того, какие части страницы можно анимировать без необходимости повторного растрирования. Каждый объект (фрейма или рендера) присваивается слою.
  • Для каждого слоя на странице выделяются текстуры.
  • Объекты (рендеры/фреймы) каждого слоя перебираются и для соответствующих слоёв выполняются команды отрисовки. Растрирование может осуществляться процессором или возможна отрисовка на графическом процессоре (GPU) через D2D/SkiaGL.
  • Все вышеперечисленные шаги могут требовать повторного использования значений, сохранённых с последнего рендеринга страницы, такая инкрементальная работа требует меньше затрат.
  • Слои страницы отправляются процессу-компоновщику, где они комбинируются со слоями для другого видимого контента (интерфейс браузера, iframe-элементы, addon-панели).
  • Вычисляются финальные позиции слоёв и через Direct3D/OpenGL отдаются композитные команды. Командные буферы GPU освобождаются для асинхронного рендеринга и фрейм отправляется для отображения на экран.

12. Рендеринг GPU

  • Во время процесса рендеринга уровни графических вычислений могут использовать процессор компьютера или графический процессор (GPU).
  • Во втором случае уровни графического программного обеспечения делят задачу на множество частей, что позволяет использовать параллелизм GPU для вычисления плавающей точки, которое требуется для процесса рендеринга.

13. Вызванное пользователем и пост-рендеринговое исполнение

После завершения рендеринга, браузер исполняет JavaScript-код в результате срабатывания некоего часового механизма (так работают дудлы на странице Google) или в результате действий пользователя (ввод поискового запроса в строку и получение рекомендаций в ответ). Также могут срабатывать плагины вроде Flash или Java (но не в рассматриваемом примере с домашней страницей Google). Скрипты могут потребовать обработки дополнительных сетевых запросов, изменять страницу или её шаблон, что приведёт к следующему этапу рендеринга и отрисовки.

  • Блог компании HTML Academy
  • Веб-разработка
  • Браузеры

Как работает Веб

Как работает Веб даст упрощённое представление о том, что происходит при просмотре веб-страницы в браузере на вашем компьютере или телефоне.

Эта теория не так важна для написания веб-кода в краткосрочной перспективе, но в скором времени вы действительно начнёте извлекать выгоду из понимания того, что происходит в фоновом режиме.

Клиенты и серверы

Компьютеры, подключённые к сети, называются клиентами и серверами. Упрощённая схема того, как они взаимодействуют, может выглядеть следующим образом:

  • Клиенты являются обычными пользователями, подключёнными к Интернету посредством устройств (например, компьютер подключён к Wi-Fi, или ваш телефон подключён к мобильной сети) и программного обеспечения, доступного на этих устройствах (как правило, браузер, например, Firefox или Chrome).
  • Серверы — это компьютеры, которые хранят веб-страницы, сайты или приложения. Когда клиентское устройство пытается получить доступ к веб-странице, копия страницы загружается с сервера на клиентский компьютер для отображения в браузере пользователя.

Остальные части панели инструментов

Клиент и сервер, о которых мы рассказали выше, не раскрывают всю суть. Есть много других компонентов, и мы опишем их ниже.

А сейчас давайте представим, что Веб — это дорога. Одна сторона дороги является клиентом, который представляет собой ваш дом. Другая сторона дороги является сервером, который представляет собой магазин. Вы хотите что-то купить в нём.

Помимо клиента и сервера, мы также должны уделить внимание:

  • Ваше Интернет-подключение: Позволяет отправлять и принимать данные по сети. Оно подобно улице между домом и магазином.
  • TCP/IP: Протокол Управления Передачей и Интернет Протокол являются коммуникационными протоколами, которые определяют, каким образом данные должны передаваться по сети. Они как транспортные средства, которые позволяют сделать заказ, пойти в магазин и купить ваши товары. В нашем примере, это как автомобиль или велосипед (или собственные ноги).
  • DNS: Система Доменных Имён напоминает записную книжку для веб-сайтов. Когда вы вводите веб-адрес в своём браузере, браузер обращается к DNS, чтобы найти реальный адрес веб-сайта, прежде чем он сможет его получить. Браузеру необходимо выяснить, на каком сервере живёт сайт, поэтому он может отправлять HTTP-сообщения в нужное место (см. Ниже). Это похоже на поиск адреса магазина, чтобы вы могли попасть в него.
  • HTTP: Протокол Передачи Гипертекста — это протокол, который определяет язык для клиентов и серверов, чтобы общаться друг с другом. Он, как язык, который вы используете, чтобы заказать ваш товар.
  • Файлы компонентов: сайт состоит из нескольких различных файлов, которые подобны различным отделам с товарами в магазине. Эти файлы бывают двух основных типов:
    • Файлы кода: сайты построены преимущественно на HTML, CSS и JavaScript, хотя вы познакомитесь с другими технологиями чуть позже.
    • Материалы: это собирательное название для всех других вещей, составляющих сайт, такие как изображения, музыка, видео, документы Word и PDF.

    Что же на самом деле происходит?

    Когда вы вводите веб-адрес в свой браузер (для нашей аналогии — посещаете магазин):

    1. Браузер обращается к DNS серверу и находит реальный адрес сервера, на котором «живёт» сайт (Вы находите адрес магазина).
    2. Браузер посылает HTTP запрос к серверу, запрашивая его отправить копию сайта для клиента (Вы идёте в магазин и заказываете товар). Это сообщение и все остальные данные, передаваемые между клиентом и сервером, передаются по интернет-соединению с использованием протокола TCP/IP.
    3. Если сервер одобряет запрос клиента, сервер отправляет клиенту статус «200 ОК», который означает: «Конечно, вы можете посмотреть на этот сайт! Вот он», а затем начинает отправку файлов сайта в браузер в виде небольших порций, называемых пакетными данными (магазин выдаёт вам ваш товар или вам привозят его домой).
    4. Браузер собирает маленькие куски в полноценный сайт и показывает его вам (товар прибывает к вашей двери — новые вещи, потрясающе!).

    DNS

    Реальные веб-адреса — неудобные, незапоминающиеся строки, которые вы вводите в адресную строку, чтобы найти ваши любимые веб-сайты. Эти строки состоят из чисел, например: 63.245.215.20 .

    Такой набор чисел называется IP-адресом и представляет собой уникальное местоположение в Интернете. Впрочем, его не очень легко запомнить, правда? Вот почему изобрели DNS. Это специальные сервера, которые связывают веб-адрес, который вы вводите в браузере (например, «mozilla.org»), с реальным IP-адресом сайта.

    Сайты можно найти непосредственно через их IP-адреса. Вы можете найти IP-адрес веб-сайта, введя его домен в инструмент, как IP Checker.

    Пакеты

    Ранее мы использовали термин «пакеты», чтобы описать формат, в котором данные передаются от сервера к клиенту. Что мы имеем в виду? В основном, когда данные передаются через Интернет, они отправляются в виде тысячи мелких кусочков, так что множество разных пользователей могут скачивать один и тот же сайт одновременно. Если бы сайты отправлялись одним большим куском, тогда бы только один пользователь мог скачать его за один раз, и это, очевидно, сделало бы пользование интернетом не эффективным и не очень радостным.

    Смотрите также

    • Как работает Интернет
    • HTTP — Протокол уровня приложений
    • HTTP: Давайте изучим его!
    • HTTP: Коды ответов

    Благодарность

    • Назад
    • Обзор: Getting started with the web

    В этом модуле

    • Установка базового программного обеспечения
    • Каким должен быть ваш веб-сайт?
    • Работа с файлами
    • Основы HTML
    • Основы CSS
    • Основы JavaScript
    • Публикация вашего веб-сайта
    • Как работает Веб

    Что происходит, когда мы открываем сайт в браузере

    Эта статья — короткий и простой перевод статьи «What happens when. », опубликованной на Гитхабе. В ней автор подробно рассказывает, что именно происходит внутри компьютера, когда мы вводим в браузере адрес сайта и нажимаем энтер. Мы убрали излишние технические подробности вроде IRQ-прерываний и ARP-запросов и добавили картинки, чтобы было проще понять суть.

    Начало

    Мы ввели адрес сайта — thecode.media — и нажали энтер. Что происходит дальше?

    Поиск сервера в интернете

    Каждый сайт в сети физически хранится на каком-то сервере. Как только браузер от нас получил адрес сайта, он должен понять, к какому серверу обратиться за данными. Но то, что мы называем адресом, на самом деле не адрес, а доменное имя.

    �� Проще говоря, когда вы садитесь в такси и говорите «Мне в „Мегу“», вы назвали водителю не адрес, а доменное имя. Водитель уже сам должен знать, где в вашем городе «Мега».

    Так вот: теперь задача браузера — определить по доменному имени адрес, на который отправлять запрос. В мире интернета этот адрес называется IP-адресом. Он есть у каждого сервера и выглядит, например, так:

    По этим числам компьютеры понимают, как связаться друг с другом и отправить нужные данные. Чтобы понять, какой именно IP-адрес у сервера с нашим сайтом, браузер делает так:

    1. Сначала смотрит, посещали мы этот сайт раньше или нет. Если посещали — возьмёт IP-адрес из истории. Так же, как водитель, который тысячу раз ездил в «Мегу».
    2. Если не посещали — посмотрит в конфигурационных файлах операционной системы. Иногда для ускорения работы некоторые IP-адреса можно прописать в конфигурации компьютера, чтобы он сразу знал, куда обращаться.
    3. Если в настройках такого нет, браузер смотрит недавние адреса в роутере, через который компьютер подключается к интернету.
    4. Если и там нет, то браузер отправляет запрос на DNS-сервер. Там точно всё есть, но результат получится медленнее, чем в остальных способах.

    DNS-сервер — это такая служба в интернете, которая отвечает всем желающим на вопрос «Какой IP у такого-то домена?». Таких серверов в интернете много, и каждый из них знает про свою часть сети. Если у ближайшего сервера нет записей о нашем домене, то он отвечает «Я не знаю, спроси у DNS-сервера покрупнее, вот его адрес». В итоге браузер найдёт DNS-сервер, который знает то, что нам нужно, и получит IP-адрес сервера с сайтом.

    Что происходит, когда мы открываем сайт в браузере

    Что ещё прочитать на эту тему:

    Отправка запроса

    Браузер нашёл IP-адрес сервера, на котором располагается наш сайт, и отправляет по этому адресу запрос типа «Я знаю, что у тебя есть вот такой домен. Мне нужна вот такая страница с этого домена с такими-то параметрами. Дай, пожалуйста».

    Чтобы всё было безопасно и данные никто не перехватил по пути, браузер и сервер договариваются шифровать все сообщения друг другу. Как только все формальности соблюдены, сервер отвечает «Да, конечно, сейчас всё отправлю». Иногда в адресе бывают ошибки, и сервер не может у себя найти нужную страницу. Тогда он отвечает «А у меня нет нужной страницы, ничем не могу помочь», и браузер показывает ошибку.

    Сервер думает

    Когда сервер получает запрос от браузера и с адресом всё в порядке, он начинает готовить данные к отправке. Для этого он смотрит, какие серверные программы отвечают за этот домен, и говорит им «Соберите мне вот эту страницу, чтобы я её отправил в браузер». Например, на сервере может стоять Вордпресс или PHP-обработчик, который на лету собирает страницу из разных фрагментов кода.

    Что происходит, когда мы открываем сайт в браузере

    Отправка данных в браузер

    Как только сервер получил от своих внутренних программ всё, что ему нужно, он отправляет результат в браузер.

    Для этого он нарезает все данные на мелкие пакеты данных по 8 килобайт, нумерует их и отправляет браузеру. Так делается для того, чтобы одновременно передавать много пакетов — в этом случае загрузка идёт быстрее. Нумерация нужна для того, чтобы браузер потом собрал все пакеты в одно целое и получил исходный документ. Если по пути пакет потерялся, браузер говорит серверу «У меня потерялись такие-то пакеты, отправь их ещё раз». И так до тех пор, пока браузер не соберёт все пакеты.

    Что происходит, когда мы открываем сайт в браузере

    Браузер думает

    Когда все пакеты собраны, браузер разбирает документ на составляющие:

    • HTML;
    • CSS;
    • JavaScript;
    • прочий код, который браузер может выполнить.

    Это нужно для того, чтобы браузер построил DOM-модель страницы. Такая модель содержит:

    • все элементы, которые есть на странице;
    • связи между ними;
    • как они взаимодействуют между собой;
    • что умеют и как реагируют на действия пользователя.

    На основе DOM-модели браузер в итоге будет рисовать страницу на экране.

    Что происходит, когда мы открываем сайт в браузере

    Отрисовка страницы

    Последнее, что нужно сделать браузеру, — взять DOM-модель, найти в ней все видимые элементы и нарисовать их на экране. Если есть JavaScript-код, то он выполняется либо до отрисовки, либо после, смотря как работает скрипт.

    Иногда во время отрисовки страницы браузер может снова запросить данные у сервера. В этом случае браузер рисует то, что есть, а остальное — когда придут данные. Пока данных нет, на странице могут быть пустые места — например, браузер отрисовал верхнее меню и статью, но ещё не подгрузил видео с ютуба.

    Всё готово

    Когда страница загрузилась и браузер всё нарисовал, мы видим готовый результат. Но даже сейчас браузер может продолжать работать над страницей:

    • выполнять JS-скрипт;
    • подгружать в фоне музыку или видео;
    • подгружать страницы, на которые переходят с этого сайта чаще всего, чтобы создать эффект моментальной загрузки новых страниц;
    • записывать что-то в куки или в локальное хранилище;
    • собирать данные о том, что вы делаете на странице;
    • и что угодно ещё, что предусмотрели программисты.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *