Этот репозиторий – это попытка ответить на извечный вопрос во время интервью: «Что происходит, когда вы вводите google.com в адресную строку браузера и нажимаете Enter?»
С той лишь разницей, что вместо «обычной» истории мы попытаемся ответить на этот вопрос как можно подробнее. Ничего не пропуская.
Это совместный процесс, так что постарайтесь помочь! В описании не хватает множества деталей, поэтому я с нетерпением жду, когда вы поможете мне их добавить! Так что отправьте нам свои замечания, пожалуйста!
Все это лицензировано под лицензией Creative Commons Zero.
Прочтите это на 简体中文 (упрощенный китайский), 日本語 (японский), 한국어 (корейский) и испанском языках.
ПРИМЕЧАНИЕ: переводы не были выверены alex/what-happens-when.
Оглавление
Table of Contents
- ЧТО ПРОИСХОДИТ, КОГДА...
- ОГЛАВЛЕНИЕ
- НАЖАТА КЛАВИША "G"
- КЛАВИША "ВВОД" НАЖАТА
- СРАБАТЫВАНИЕ ПРЕРЫВАНИЯ [НЕ ДЛЯ USB-КЛАВИАТУР]
- (В WINDOWS) ОТПРАВКА В ПРИЛОЖЕНИЕ СООБЩЕНИЯ О НАЖАТИИ КЛАВИШИ WM_KEYDOWN
- (В OS X) KEYDOWN NSEVENT ОТПРАВЛЯЕТСЯ В ПРИЛОЖЕНИЕ
- (В GNU/LINUX) СЕРВЕР XORG ПРОСЛУШИВАЕТ КОДЫ КЛАВИШ
- ОБРАБОТКА URL
- ЭТО URL ИЛИ ПОИСКОВЫЙ ЗАПРОС?
- ПРЕОБРАЗОВАНИЕ НЕ-ASCII UNICODE СИМВОЛОВ В HOSTNAME
- ПРОВЕРКА HSTS СПИСКА
- DNS-ПОИСК
- ARP-ПРОЦЕСС
- ОТКРЫТИЕ ПОРТА
- TLS-СОЕДИНЕНИЕ
- ЕСЛИ ПАКЕТ ОТКЛОНЕН
- HTTP-ПРОТОКОЛ
- ДЕСКРИПТОР ЗАПРОСА HTTP-СЕРВЕРА
- ЗА КУЛИСАМИ БРАУЗЕРА
- БРАУЗЕР
- ПАРСИНГ HTML
- CSS ИНТЕРПРЕТАЦИЯ
- РЕНДЕРИНГ СТРАНИЦЫ
- ГРАФИЧЕСКИЙ РЕНДЕРИНГ
- ОКОННЫЙ СЕРВЕР
- ПОСТ-РЕНДЕРИНГ И ОБРАБОТКА ИНИЦИИРОВАННАЯ ПОЛЬЗОВАТЕЛЕМ
Нажата клавиша "g"
В следующих разделах объясняются физические действия c клавиатурой и то как их обрабатывает операционная система (ОС). Когда вы нажимаете клавишу «g», браузер получает событие и срабатывают функции автозаполнения. В зависимости от алгоритма вашего браузера и от того, находитесь ли вы в режиме приватности/инкогнито или нет, вам будут представлены различные подсказки в раскрывающемся списке чуть ниже поля ввода URL-адреса. Большинство этих алгоритмов сортируют и приоритезируют результаты на основе истории поиска, закладок, файлов cookie и популярных поисковых запросов в Интернете. Когда вы набираете «google.com», запускается множество блоков кода, и возможные подсказки будут уточняться с каждым нажатием клавиши. Вы можете даже получить предложение «google.com», прежде чем вы закончите вводить его.
Клавиша "ввод" нажата
Чтобы выбрать точку старта, давайте нажмем клавишу Enter на клавиатуре и нажмем ее. В этот момент электрическая цепь, закрепленная за клавишей ввода, замыкается (напрямую или через емкостное соединение). Это позволяет небольшому количеству тока протекать по логической схеме клавиатуры, которая сканирует состояние каждой клавиши, за одно подавляет посторонние электрические шумы и преобразует сигнал в целое число кода нажатой клавиши, в нашем случае в код 13. Далее контроллер клавиатуры кодирует код нажатой клавиши и передает его далее компьютеру. Сегодня это почти всегда происходит через соединение с универсальной последовательной шиной (USB) или Bluetooth, но в старые времена подключение клавиатуры выполнялось через соединения PS/2 или ADB.
В случае USB-клавиатуры:
- USB клавиатура питается от напряжения 5 В, подаваемого на контакт 1 USB разъема от компьютера.
- Сгенерированный код клавиши сохраняется во внутренней памяти клавиатуры в регистре, называемом «endpoint».
- USB контроллер со стороны ПК опрашивает этот регистр внутренней памяти клавиатуры каждые ~ 10 мс (минимальное значение) и получает сохраненное в регистре значение кода клавиши.
- Это значение передается в USB SIE (модуль последовательного интерфейса) для преобразования в один или несколько пакетов USB, соответствующих низкоуровневому протоколу USB.
- Эти пакеты передаются дифференциальным электрическим сигналом через контакты D+ и D- (2 контакта в середине) с максимальной скоростью 1,5 Мбит/с, поскольку устройство HID (Human Interface Device) всегда объявляется «низкоскоростным устройством». " (режим совместимости с USB 2.0).
- Затем этот сигнал декодируется USB-контроллером компьютера и интерпретируется драйвером универсальной клавиатуры устройства HID (Human Interface Device) компьютера. Затем значение ключа передается на уровень аппаратной абстракции операционной системы.
В случае виртуальной клавиатуры (как в устройствах с сенсорным экраном):
- Когда пользователь прикладывает палец к современному емкостному сенсорному экрану, на палец передается небольшое количество тока. Это замыкает цепь через электростатическое поле проводящего слоя и создает падение напряжения в этой точке экрана. Затем screen controller создает прерывание, сообщая координаты нажатия.
- Далее мобильная ОС уведомляет исполняемое приложение о нажатии в одном из элементов графического интерфейса приложения (который теперь является кнопками приложения виртуальной клавиатуры).
- Виртуальная клавиатура теперь может сгенерировать программное прерывание для отправки сообщения о нажатии клавиши обратно в ОС.
- Это прерывание уведомляет активное приложение о событии «нажата клавиша».
Срабатывание прерывания [НЕ для USB-клавиатур]
Клавиатура отправляет сигналы по каналу запросов прерывания (IRQ), которые преобразуется в interrupt vector (целое число) контроллером прерываний. ЦП использует Interrupt Descriptor Table(IDT) для сопоставления векторов прерываний с функциями ( interrupt handlers), которые предоставляются ядром. Когда происходит прерывание, ЦП индексирует IDT вектором прерывания и запускает необходимый обработчик. Таким образом активируется ядро.
(В Windows) отправка в приложение сообщения о нажатии клавиши WM_KEYDOWN.
Интерфейс HID передает событие о нажатия клавиши KBDHID.sys драйверу, который преобразует сообщение HID в скан-код. В нашем случае скан-код VK_RETURN( 0x0D). Драйвер KBDHID.sys взаимодействует с KBDCLASS.sys (драйвер класса клавиатуры). Этот драйвер отвечает за безопасную обработку всего ввода данных с клавиатуры. Далее драйвер вызывает Win32K.sys (после возможной передачи сообщения через установленные сторонние фильтры клавиатуры). Все это происходит на ядровом уровне.
Win32K.sys определяет какое окно является активным посредством GetForegroundWindow()API. Этот API дает окну обработать поле ввода адреса в браузере. Далее основной обработчик сообщений Windows «message pump» вызывает SendMessage(hWnd, WM_KEYDOWN, VK_RETURN, lParam). lParam - это битовая маска, которая передает следующую информацию о нажатии клавиши: количество повторений (в данном случае 0), фактический код сканирования (может зависеть от OEM, но обычно не для VK_RETURN), были ли также нажаты расширенные клавиши (например, alt, shift, ctrl) (их не было), и некоторые другие состояния.
Windows SendMessageAPI — это простая функция, которая добавляет сообщение в очередь для определенного дескриптора окна ( hWnd). Позже вызывается основная функция обработки сообщений (называемая a WindowProc), назначенная для hWnd обработки каждого сообщения в очереди.
Активное окно ( hWnd) является элементом управления редактированием, и WindowProc в этом случае имеет обработчик сообщений для WM_KEYDOWN сообщений. Этот код просматривает третий параметр, который был передан в SendMessage( wParam), и, поскольку это VK_RETURN, то он понимает, что пользователь нажал клавишу ENTER.
(В OS X) KeyDown NSEvent отправляется в приложение
Сигнал прерывания запускает событие прерывания в драйвере клавиатуры kext I/O Kit. Драйвер транслирует сигнал в код клавиши, который передается WindowServer процессу OS X. В результате событие WindowServer отправляется любому соответствующему (например, активному или слушающему/ожидающему) приложению через порт Mach, где оно помещается в очередь событий. После этого события могут быть прочитаны из очереди потоками с достаточными привилегиями, вызывающими функцию mach_ipc_dispatch. Чаще всего это происходит и обрабатывается в NSApplication - основном цикле событий через объект NSEvent. NSEventType KeyDown
(В GNU/Linux) сервер Xorg прослушивает коды клавиш
Когда используется графический X server, X использует универсальный драйвер событий evdev для обработки события нажатия клавиши. Повторное сопоставление кодов клавиш со скан-кодами выполняется с помощью определенных раскладок и правил X server. Когда сопоставление скан-кода нажатой клавиши выполнено, X server отправляет символ в window manager (DWM, metacity, i3 и т. д.), а затем, window manager в свою очередь, отправляет символ в активное окно. Графический API окна, которое получает символ, выводит соответствующий символ шрифта в нужном поле.
Обработка URL
- Браузер теперь имеет следующую информацию, содержащуюся в URL-адресе (унифицированный указатель ресурсов):
- Protocol"http" - Используйте «Протокол передачи гипертекста»
- Resource"/" - Получить главную (индексную) страницу
Это URL или поисковый запрос?
Когда протокол или валидное доменное имя не указаны, браузер продолжает передавать текст, указанный в поле адреса, в дефолтный обработчик поисковых запросов браузера. Во многих случаях к URL-адресу добавляется специальный фрагмент текста, сообщающий поисковому движку/обработчику, что он получен из строки URL-адреса определенного браузера.
Преобразование не-ASCII Unicode символов в hostname
- Браузер проверяет имя хоста на наличие символов, не входящих в a-z, A-Z, 0-9, -или ..
- Поскольку имя хоста google.com то у нас не будет неASCII unicod символов, а если бы они были, то браузер применил бы кодировку Punycode к части имени хоста URL-адреса.
Проверка HSTS списка
- Браузер проверяет свой список «предварительно загруженных HSTS (HTTP Strict Transport Security)». Это список веб-сайтов, которые требуют соединение только через HTTPS.
- Если веб-сайт есть в списке, браузер отправляет запрос по протоколу HTTPS вместо HTTP. В противном случае первоначальный запрос отправляется через HTTP. (Обратите внимание, что веб-сайт по-прежнему может использовать политику HSTS, не будучи в списке HSTS. Первый HTTP-запрос к веб-сайту со стороны пользователя получит ответ, требующий отправку пользователем только HTTPS-запросов. Однако этот единственный HTTP-запрос потенциально может сделать пользователя уязвимым для атаки с понижением версии , поэтому список HSTS включен в современные веб-браузеры.)
DNS-поиск
- Браузер проверяет, находится ли домен в его кеше. (чтобы увидеть кеш DNS в Chrome, перейдите по адресу chrome://net-internals/#dns).
- Если он не найден, браузер вызывает библиотечную функцию gethostbyname (может отличаться в зависимости от ОС) для поиска.
- Gethostbyname проверяет, может ли имя хоста быть доступно по ссылке в локальном hosts файле (расположение которого зависит от ОС ), прежде чем пытаться получить имя хоста через DNS.
- Если домен не кеширован в gethostbyname и если он не может быть найдет в hosts файле, тогда выполняется запрос к DNS-серверу, настроенном в сетевом стеке. Обычно это локальный маршрутизатор или кэшированный DNS-сервер интернет-провайдера.
- Если DNS-сервер находится в той же подсети, сетевая библиотека следует приведенной ниже ARP process инструкции для DNS-сервера.
- Если DNS-сервер находится в другой подсети, сетевая библиотека следует указанному ниже ARP process для шлюза IP по умолчанию.
ARP-процесс
Чтобы отправить широковещательную рассылку ARP (протокол разрешения адресов), библиотеке сетевого стека требуется целевой IP-адрес для поиска. Ей также необходимо знать MAC-адрес интерфейса используемого для отправки широковещательной рассылки ARP.
Кэш ARP сначала проверяется на наличие записи ARP для целевого IP. Если он есть в кеше, библиотечная функция возвращает результат: Target IP = MAC.
Если записи нет в кэше ARP:
- просматривается таблица маршрутов, чтобы определить, находится ли целевой IP-адрес в какой-либо из подсетей в локальной таблице маршрутов. Если локальный маршрут находится, библиотека использует интерфейс, связанный с этой подсетью. Если маршрута нет, библиотека использует интерфейс, который имеет подсеть нашего шлюза по умолчанию.
- Выполняется поиск MAC-адреса выбранного сетевого интерфейса.
- Сетевая библиотека отправляет ARP-запрос уровня 2 (канальный уровень модели OSI):
ARP Request:
MAC-адрес отправителя: интерфейс:mac:адрес:здесь
IP-адрес отправителя: interface.ip.goes.here
Целевой MAC-адрес: FF:FF:FF:FF:FF:FF (широковещательный)
Целевой IP: target.ip.goes.here
В зависимости от типа оборудования между компьютером и роутером:
прямое подключение:
- Если компьютер напрямую подключен к маршрутизатору, маршрутизатор отвечает ARP Reply (см. ниже)
Hub:
- Если компьютер подключен к концентратору (hub), hub будет широковещательную рассылку ARP запроса во все порты. Если маршрутизатор подключен к тому же «проводу», он ответит ARP Reply (см. ниже).
Switch:
- Если компьютер подключен к коммутатору (switch), switch проверит свою локальную таблицу CAM/MAC, чтобы определить, есть ли порт имеющий искомый MAC-адрес. Если у коммутатора нет записи о нужном MAC-адресе, он ретранслирует запрос ARP на все остальные порты.
- Если у коммутатора есть запись в таблице MAC/CAM, он отправит запрос ARP на порт, который имеет нужным нам MAC-адрес.
- Если маршрутизатор находится на том же «проводе», он ответит ARP Reply (см. ниже)
ARP Reply:
MAC-адрес отправителя: цель:mac:адрес:здесь
IP отправителя: target.ip.goes.here
Целевой MAC: интерфейс: mac: адрес: здесь
Целевой IP: interface.ip.goes.here
Теперь, когда у сетевой библиотеки есть IP-адрес либо нашего DNS-сервера, либо шлюза по умолчанию, она может возобновить свой процесс DNS:
- DNS-клиент устанавливает сокет для UDP-порта 53 на DNS-сервере, используя исходный порт выше 1023.
- Если размер ответа слишком велик, то будет использоваться TCP.
- Если DNS-сервер локального/провайдера не имеет его, то выполняется рекурсивный поиск, который перемещается по списку DNS-серверов до тех пор, пока не будет достигнут SOA, и, если когда он найден, возвращается ответ.
Открытие порта
Как только браузер получает IP-адрес целевого сервера, он берет его и указанный номер порта из URL-адреса (протокол HTTP по умолчанию использует порт 80, а HTTPS — порт 443) и вызывает функцию системной библиотеки с именем socket и запрашивает TCP поток сокета - AF_INET/AF_INET6 и SOCK_STREAM.
- Этот запрос сначала передается на транспортный уровень, где создается сегмент TCP. Порт назначения добавляется в заголовок, а исходный порт выбирается из динамического диапазона портов ядра (ip_local_port_range в Linux).
- Этот сегмент отправляется на сетевой уровень, который упаковывает дополнительный заголовок IP. IP-адрес целевого сервера, а также адрес текущей машины вставляются для формирования пакета.
- Затем пакет поступает на канальный уровень. Добавляется заголовок фрейма, который включает MAC-адрес сетевого карты компьютера, а также MAC-адрес шлюза (локального маршрутизатора). Как и прежде, если ядру не известен MAC-адрес шлюза, оно должно рассылать ARP-запрос, чтобы найти его.
В этот момент пакет готов к передаче через:
Для большинства домашних подключений к Интернету или подключений для малого бизнеса пакет передается с вашего компьютера, возможно, через локальную сеть, а затем через модем (модулятор / демодулятор), который преобразует цифровые 1 и 0 сигналы в аналоговый сигнал, подходящий для передачи по телефону, кабелю или беспроводной телефонной связи.. На другом конце соединения находится еще один модем, который преобразует аналоговый сигнал обратно в цифровые данные для обработки следующим сетевым узлом, где адреса отправителя и получателя будут дополнительно проанализированы .
Большинство крупных предприятий и некоторые новые жилые помещения будут иметь оптоволоконные или прямые соединения Ethernet, и в этом случае данные остаются цифровыми и передаются непосредственно на следующий сетевой узел для обработки.
В конце концов пакет достигнет маршрутизатора, управляющего локальной подсетью. Оттуда он продолжит движение к конечным маршрутизаторам автономной системы (AS), другим AS и, наконец, к целевому серверу. Каждый маршрутизатор на своем пути извлекает адрес назначения из заголовка IP и направляет его к соответствующему следующему переходу. Поле time to live (TTL) в заголовке IP уменьшается на единицу с каждым проходом маршрутизатора. Пакет будет сброшен, если поле TTL достигнет нуля или если у текущего маршрутизатора не останется места в очереди (возможно, из-за перегрузки сети).
Эти отправка и получение происходят несколько в рамках TCP соединения:
- Клиент выбирает начальный порядковый номер (ISN) и отправляет пакет на сервер с установленным битом SYN, чтобы указать, что он устанавливает ISN.
-
Сервер получает SYN и если он в состоянии принятия:
- Сервер выбирает свой начальный порядковый номер
- Сервер отправляет SYN, чтобы указать, что он выбирает свой ISN
- Сервер копирует (клиентский ISN +1) в свое поле ACK и добавляет флаг ACK, чтобы указать, что он подтверждает получение первого пакета.
-
Клиент подтверждает соединение, отправляя пакет:
- Увеличивает собственный порядковый номер
- Увеличивает номер подтверждения получателя
- Устанавливает поле ACK
-
Данные передаются следующим образом:
- Когда одна сторона отправляет N байтов данных, она увеличивает свой SEQ на это число.
- Когда другая сторона подтверждает получение этого пакета (или цепочки пакетов), она отправляет пакет ACK со значением ACK, равным последней полученной последовательности от другой стороны.
-
Чтобы закрыть соединение:
- Инициатор посылает пакет FIN
- Другие стороны принимают пакет FIN и отправляют свои собственные пакеты FIN.
- Инициатор подтверждает FIN сообщения с помощью ACK
TLS-соединение
- Клиентский ПК отправляет сообщение ClientHello на сервер со своей версией безопасности транспортного уровня (TLS), списком доступных алгоритмов шифрования и методов сжатия.
- Сервер отвечает клиенту ServerHello сообщением с версией TLS, выбранным шифром, выбранными методами сжатия и общедоступным сертификатом сервера, подписанным ЦС (центром сертификации). Сертификат содержит открытый ключ, который будет использоваться клиентом для шифрования остальной части сообщений, пока не будет согласован симметричный ключ.
- Клиент сверяет цифровой сертификат сервера со своим списком доверенных ЦС. Если доверие может быть установлено на основе ЦС, клиент генерирует строку псевдослучайных байтов и шифрует ее с помощью открытого ключа сервера. Эти случайные байты могут быть использованы для определения симметричного ключа.
- Сервер расшифровывает случайные байты с помощью своего закрытого ключа и использует эти байты для создания собственной копии симметричного главного ключа.
- Клиент отправляет Finished сообщение на сервер, до этого момента шифруя хэш передачи с помощью симметричного ключа.
- Сервер генерирует свой собственный хэш, а затем расшифровывает хэш, отправленный клиентом, чтобы убедиться, что он совпадает. Если они совпадают, он отправляет клиенту собственное Finished сообщение, также зашифрованное с помощью симметричного ключа.
- С этого момента сеанс TLS передает данные приложения (HTTP), зашифрованные с помощью согласованного симметричного ключа.
Если пакет отклонен
Иногда из-за перегрузки сети или нестабильного аппаратного соединения пакеты TLS сбрасываются до того, как они достигнут своего конечного пункта назначения. После этого отправитель должен решить, как реагировать. Для таких ситуаций есть алгоритм, именуемый контроль перегрузки TCP . Это зависит от отправителя; наиболее распространённые являются cubic алгоритмы в новых операционных системах и алгоритмы New Reno почти во всех остальных.
- Клиент выбирает окно перегрузки на основе максимального размера сегмента (MSS) соединения.
- Для каждого подтвержденного пакета размер окна удваивается, пока не достигнет 'slow-start threshold'. В некоторых реализациях этот порог является адаптивным.
- После достижения 'slow-start threshold' окно увеличивается аддитивно для каждого подтвержденного пакета. Если пакет сброшен, окно экспоненциально уменьшается до тех пор, пока не будет подтвержден другой пакет.
HTTP-протокол
Если используемый веб-браузер был написан Google, вместо отправки HTTP-запроса для получения страницы он отправит запрос на попытку согласовать с сервером «обновления» с HTTP до протокола SPDY.
Если клиент использует протокол HTTP и не поддерживает SPDY, он отправляет запрос на сервер вида:
ПОЛУЧИТЬ/HTTP/1.1
Хост: google.com
Подключение: закрыть
[другие заголовки]
где [other headers] относится к серии пар ключ-значение, разделенных двоеточиями, отформатированных в соответствии со спецификацией HTTP и разделенных одиночными символами новой строки. (Это предполагает, что используемый веб-браузер не содержит ошибок, нарушающих спецификацию HTTP. Это также предполагает, что веб-браузер использует HTTP/1.1, в противном случае он может не включать заголовок Host в запрос, а версия, указанная в запросе GET, будет HTTP/1.0 либо HTTP/0.9.)
HTTP/1.1 определяет опцию «закрыть» соединение, чтобы отправитель сигнализировал, что соединение будет закрыто после завершения ответа. Например,
Connection: close
Приложения HTTP/1.1, которые не поддерживают постоянные соединения, ДОЛЖНЫ включать параметр «закрыть» соединение в каждое сообщение.
После отправки запроса и заголовков веб-браузер отправляет на сервер одну пустую новую строку, указывающую, что содержимое запроса выполнено.
Сервер отвечает кодом ответа, обозначающим статус запроса, и отвечает ответом вида:
200 OK
[response headers]
За которым следует одна новая строка, а затем отправляется полезная информация HTML-содержимого www.google.com. Затем сервер может либо закрыть соединение, либо, если заголовки, отправленные клиентом, запросили это, оставить соединение открытым для повторного использования в последующих запросах.
Если заголовки HTTP, отправленные веб-браузером, содержали достаточно информации для веб-сервера, чтобы определить, не изменилась ли версия файла, кэшированная веб-браузером, с момента последнего извлечения (т. е. если веб-браузер включил ETag заголовок), он может вместо этого ответить запросом формы:
304 Not Modified
[response headers]
и без полезной информации в ответе, а веб-браузер вместо этого извлечет HTML из своего кеша.
После синтаксического анализа HTML веб-браузер (и сервер) повторяет этот процесс для каждого ресурса (изображения, CSS, favicon.ico и т. д.), на который ссылается HTML-страница, за исключением того, что вместо GET / HTTP/1.1 запроса будет запрос GET /$(URL относительно www.google.com) HTTP/1.1.
Если HTML ссылается на ресурс в отличном от www.google.com домене, веб-браузер возвращается к шагам, связанным с поиском другого домена, и выполняет все шаги по установлению пути до этого домена. В Host заголовке запроса будет указано соответствующее имя сервера вместо google.com.
Дескриптор запроса HTTP-сервера
Сервер HTTPD (HTTP Daemon) – занимается обработкой запросов/ответов на стороне сервера. Наиболее распространенными серверами HTTPD являются Apache или nginx для Linux и IIS для Windows.
- HTTPD (демон HTTP) получает запрос.
-
Сервер разбивает запрос на следующие параметры:
- Метод HTTP-запроса (либо GET, HEAD, POST, PUT, PATCH, DELETE, CONNECT, OPTIONS, или TRACE). В случае URL, введенного непосредственно в адресную строку, это будет GET.
- Домен, в данном случае — google.com.
- Запрошенный путь/страница, в данном случае - / (поскольку конкретный путь/страница не запрашивался, / является путем по умолчанию).
- Сервер проверяет, что на сервере настроен виртуальный хост, соответствующий google.com.
- Сервер проверяет, может ли google.com принимать запросы GET.
- Сервер проверяет, разрешено ли клиенту использовать этот метод (по IP, аутентификации и т. д.).
- Если на сервере установлен модуль перезаписи (например, mod_rewrite для Apache или URL Rewrite для IIS), он пытается сопоставить запрос с одним из настроенных правил. Если соответствующее правило найдено, сервер использует это правило для перезаписи запроса.
- Сервер переходит к извлечению контента, соответствующего запросу, в нашем случае он вернется к индексному файлу, так как «/» является основным файлом (в некоторых случаях это можно переопределить, но это наиболее распространенный метод).
- Сервер анализирует файл в соответствии с обработчиком. Если Google работает на PHP, сервер использует PHP для интерпретации индексного файла и передает результат клиенту.
За кулисами браузера
Как только сервер предоставляет ресурсы (HTML, CSS, JS, изображения и т. д.) браузеру, он выполняет следующей процесс:
- Парсинг — HTML, CSS, JS
- Рендеринг - Построение дерева DOM → Дерево рендеринга → Макет дерева рендеринга → Рисование дерева рендеринга
Браузер
Функционал браузера заключается в представлении выбранного вами веб-ресурса путем запроса его с сервера и отображения в окне браузера. Ресурс обычно представляет собой HTML-документ, но также может быть PDF-файлом, изображением или другим типом контента. Местоположение ресурса указывается пользователем с помощью URI (Uniform Resource Identifier).
То, как браузер интерпретирует и отображает HTML-файлы, указано в спецификациях HTML и CSS. Эти спецификации поддерживаются организацией W3C (Консорциум World Wide Web), которая является организацией по стандартизации для Интернета.
Пользовательские интерфейсы браузеров имеют много общего друг с другом. К числу распространенных элементов пользовательского интерфейса относятся:
- Адресная строка для вставки URI
- Кнопки назад и вперед
- Варианты закладок
- Кнопки «Обновить» и «Стоп» для обновления или остановки загрузки текущих документов.
- Кнопка «Домой», которая ведет на домашнюю страницу
Высокоуровневая структура браузера
Компоненты браузеров:
- Пользовательский интерфейс: пользовательский интерфейс включает в себя адресную строку, кнопку «назад/вперед», меню закладок и т. д. Каждая часть отображения браузера, кроме окна, в котором вы видите запрошенную страницу.
- Движок браузера. Движок браузера распределяет действия между пользовательским интерфейсом и движком рендеринга.
- Движок рендеринга. Движок рендеринга отвечает за отображение запрошенного контента. Например, если запрошенный контент представляет собой HTML, движок рендеринга анализирует HTML и CSS и отображает проанализированный контент на экране.
- Сетевой уровень: сеть обрабатывает сетевые вызовы, такие как HTTP-запросы, используя различные реализации для разных платформ за платформо-независимым интерфейсом.
- Серверная часть пользовательского интерфейса: базовая часть пользовательского интерфейса используется для рисования основных виджетов, таких как поля со списком и окна. Этот бэкэнд предоставляет общий интерфейс, который не зависит от платформы. Внутри него используются методы пользовательского интерфейса операционной системы.
- Движок JavaScript : движок JavaScript используется для анализа и выполнения кода JavaScript.
- Хранилище данных. Хранилище данных — это уровень хранения. Браузеру может потребоваться сохранить все виды данных локально, например файлы cookie. Браузеры также поддерживают такие механизмы хранения, как localStorage, IndexedDB, WebSQL и FileSystem.
Парсинг HTML
Механизм рендеринга начинает получать содержимое запрошенного документа с сетевого уровня. Обычно это делается кусками по 8 КБ.
Основная задача синтаксического анализатора HTML заключается в преобразовании HTML-разметки в дерево синтаксического анализа.
Выходное дерево («дерево синтаксического анализа») представляет собой дерево элементов DOM и узлов атрибутов. DOM — это сокращение от объектной модели документа. Это объектное представление HTML-документа и интерфейс HTML-элементов к внешнему миру, подобноJavaScript. Корнем дерева является объект «Документ». До каких-либо манипуляций с помощью скриптов, DOM имеет почти одноранговое отношение к разметке.
Алгоритм разбора
HTML нельзя анализировать с помощью обычных парсеров «сверху вниз» или «снизу вверх».
Причины:
- Всепрощающая природа языка.
- Факт того, что браузеры обладают традиционной устойчивостью к общеизвестным ошибкам некорректного HTML.
- Процесс разбора является реентерабельным. Для других языков источник не изменяется во время синтаксического анализа, но в HTML динамический код (например, элементы скрипта, содержащие вызовы document.write()) могут добавлять дополнительные токены, поэтому процесс парсинга фактически изменяет ввод.
Не имея возможности использовать обычные методы парсинга, браузер использует собственный парсер для анализа HTML. Алгоритм разбора подробно описан в спецификации HTML5.
Алгоритм состоит из двух этапов: токенизация и построение дерева.
Действия после завершения парсинга
Браузер начинает получать внешние ресурсы, связанные со страницей (CSS, изображения, файлы JavaScript и т. д.).
На этом этапе браузер помечает документ как интерактивный и начинает анализировать скрипты, находящиеся в «отложенном» режиме: те, которые должны быть выполнены после разбора документа. Состояние документа устанавливается на «завершено», и запускается событие «загрузка».
Обратите внимание, что на HTML-странице никогда не возникает ошибка «Недопустимый синтаксис». Браузеры исправляют любой недопустимый контент и продолжают работу.
CSS интерпретация
- Анализ файлов CSS, <style> содержимого тегов и style значений атрибутов с использованием «лексической и синтаксической грамматики CSS».
- Каждый файл CSS разбирается в файл StyleSheet object, где каждый объект содержит правила CSS с селекторами и объектами, соответствующими грамматике CSS.
- Парсер CSS может быть нисходящим или восходящим, когда используется определенный генератор парсера.
Рендеринг страницы
- Создайте «Дерево фреймов» или «Дерево рендеринга», пройдясь по узлам DOM и вычислив значения стиля CSS для каждого узла.
- Рассчитайте предпочтительную ширину каждого узла в «Дереве фреймов» снизу вверх, суммируя предпочтительную ширину дочерних узлов и горизонтальные поля, границы и отступы узла.
- Вычислите фактическую ширину каждого узла сверху вниз, распределив доступную ширину каждого узла между его дочерним элементам.
- Вычислите высоту каждого узла снизу вверх, применяя перенос текста и суммируя высоты дочерних узлов и поля, границы и отступы узла.
- Вычислите координаты каждого узла, используя информацию, рассчитанную выше.
- Более сложные шаги выполняются, когда элементы floated, позиционируются absolutely или relatively используются другие сложные функции. За более подробной информации обратитесь к http://dev.w3.org/csswg/css2/ и http://www.w3.org/Style/CSS/current-work
- Создайте слои, чтобы описать, какие части страницы можно анимировать как группу без повторного растрирования. Каждый объект кадра/рендеринга присваивается слою.
- Текстуры выделяются для каждого слоя страницы.
- Просматриваются объекты кадра/рендеринга для каждого слоя, и команды рисования выполняются для соответствующего слоя. Это может быть растрировано ЦП или отрисовано на графическом процессоре напрямую с помощью D2D/SkiaGL.
- Все вышеперечисленные шаги могут повторно использовать расчетные значения, полученные при последнем отображении веб-страницы, поэтому дополнительные изменения требуют меньше работы.
- Слои страницы отправляются в процесс компоновки, где они объединяются со слоями для другого видимого контента, такого как хром браузера, фреймы и дополнительные панели.
- Окончательные положения слоя вычисляются, и составные команды выдаются через Direct3D/OpenGL. Буфер(ы) команд графического процессора сбрасываются в графический процессор для асинхронного рендеринга, а кадр отправляется на сервер окон.
Графический рендеринг
- В процессе рендеринга графические вычисление уровни могут также использовать ЦП или графический процессор GPU.
- При использовании GPU для вычислений графического рендеринга уровни графического программного обеспечения разбивают задачу на несколько частей, поэтому он может использовать преимущества массивного параллелизма GPU для вычислений с плавающей запятой, необходимых в процессе рендеринга.
Оконный сервер
Пост-рендеринг и обработка инициированная пользователем
После завершения рендеринга браузер выполняет код JavaScript в результате некоторого механизма синхронизации (например, анимации Google Doodle) или взаимодействия с пользователем (ввод запроса в поле поиска и получение предложений). Такие плагины, как Flash или Java, также могут выполняться, хотя в настоящее время их нет на главной странице Google. Сценарии могут вызвать выполнение дополнительных сетевых запросов, а также изменить страницу или ее макет, что приведет к еще одному раунду рендеринга и рисования страницы.
Оригинал статьи