Открытие сокета
Когда браузер получает IP-адрес конечного сервера, то он берёт эту информацию и данные об используемом порте из URL (80 порт для HTTP, 443 для HTTPS) и осуществляет вызов функции socket системной библиотеки и запрашивает поток TCP сокета — AF_INET и SOCK_STREAM.
- Этот запрос сначала проходит через транспортный уровень, где собирается TCP-сегмент. В заголовок добавляется порт назначения, исходный порт выбирается из динамического пула ядра (настройка net.ipv4.ip_local_port_range в Linux).
- Получившийся сегмент отправляется на сетевой уровень, на котором добавляется дополнительный IP-заголовок. Также включаются IP-адрес сервера назначения и адрес текущей машины — после этого пакет сформирован. Тут же происходит выбор исходящего интерфейса, будет использоваться настройка приоритета использования интерфейсов для исходящего трафика (например, файл /etc/gai.conf).
- Пакет передаётся на канальный уровень. Добавляется заголовок кадра, включающий MAC-адрес сетевой карты (NIC) компьютера, а также MAC-адрес шлюза (локального роутера). Как и на предыдущих этапах, если ядру ничего не известно о MAC-адресе шлюза, то для его нахождения отправляется широковещательный ARP-запрос.
На этой точке пакет готов к передаче через:
- Ethernet
- WiFi
- По сотовой связи
В случае интернет-соединения большинства частных пользователей или небольших компаний пакет будет отправлен с компьютера, через локальную сеть, а затем через модем (MOdulator/DEModulator), который транслирует цифровые единицы и нули в аналоговый сигнал, подходящий для передачи по телефонной линии, кабелю или беспроводным телефонным соединениям. На другой стороне соединения расположен другой модем, который конвертирует аналоговый сигнал в цифровые данные и передаёт их следующему сетевому узлу, где происходит дальнейший анализ данных об отправителе и получателе.
В конечном итоге пакет доберётся до маршрутизатора, управляющего локальной подсетью, так же называемого шлюзом. Этот шлюз-маршрутизатор может иметь много VLAN (виртуальных локальных сетей), которые разделяет IP-подсети. В зависимости от IP и подсети, входящий фрейм данных будет приземляться на физический порт, затем заголовок Ethernet пакета (в случае Ethernet
)
будет удален, останется IP-адрес источника, IP-адрес назначения и информация о портах. Маршрутизаторы поддерживают свою таблицу маршрутизации пакетов от входящего интерфейса к исходящему интерфейсу, этот маршрутизатор читает заголовок IP-пакета и выполняет поиск в локальной таблице маршрутизации (которая строится с использованием
статических маршрутов или с использованием динамических протоколов, таких как BGP, OSPF), чтобы найти исходящий интерфейс. Перед маршрутизацией пакета в заголовке IP из поля TTL (time to live) будет вычтена 1 (используется для предотвращения бесконечного зацикливания пакетов, пакет будет отброшен, если поле TTL достигнет нуля или если текущий маршрутизатор не имеет места в своей очереди / буферах (возможно, из-за перегрузки сети) или из-за ошибочных соединений и плохого CRC.). Помимо изменения TTL могут быть изменены другие поля, например если пакеты будут фрагментированы из-за меньшего размера MTU на исходящем интерфейсе, то маршрутизатор пошлет IP пакеты в так называемых чанках (chunks) - порции, и маршрутизатор перепишет IP-заголовки основываясь на оригинальном IP-пакете, также будут изменены контрольные суммы и т.д. Наконец, эти пакеты снова будут инкапсулированы во
фрейм Ethernet или в любой другой поддерживаемый тип, который поддерживается на интерфейсе и отправлены
следующему сетевому узлу
для аналогичной обработки. Оттуда он продолжит движение к маршрутизаторам на пути, проходящем через различные автономные системы (ASN - это уникальный номер, назначенный поставщикам интернет-услуг для идентификации себя в Интернете и маршрутизации интернет-трафика. Протокол BGP-Border Gateway Protocol поддерживает большие таблицы маршрутизации в маршрутизаторах ISP и ретрансляции пакетов в пункт назначения), а затем, наконец, достигает сервера назначения, где он передается в стек TCP / IP на сервере для дальнейшей обработки и доставки приложениям.
Во время TCP-соединения происходит множество подобных запросов и ответов.
Жизненный цикл TCP-соединения
a. Клиент выбирает номер начальной последовательности (ISN) и отправляет пакет серверу с установленным битом SYN для открытия соединения.
b. Сервер получает пакет с битом SYN и, если готов к установлению соединения, то:
- Выбирает собственный номер начальной последовательности;
- Устанавливает SYN-бит, чтобы сообщить о выборе начальной последовательности;
- Копирует ISN клиента +1 в поле ACK и добавляет ACK-флаг для обозначения подтверждения получения первого пакета.
c. Клиент подтверждает соединение путём отправки пакета:
- Увеличивает номер своей начальной последовательности;
- Увеличивает номер подтверждения получения;
- Устанавливает поле ACK.
d. Данные передаются следующим образом:
- Когда одна сторона отправляет N байтов, то увеличивает значение поля SEQ на это число.
- Когда вторая сторона подтверждает получение этого пакета (или цепочки пакетов), она отправляет пакет ACK, в котором значение поля ACK равняется последней полученной последовательности.
e. Закрытие соединения:
- Сторона, которая хочет закрыть соединение, отправляет пакет FIN;
- Другая сторона подтверждает FIN (с помощью ACK) и отправляет собственный FIN-пакет;
- Инициатор прекращения соединения подтверждает получение FIN отправкой собственного ACK.
TCP Windowing
Чтобы установить максимально возможную и надежную пропускную способность, отправитель и получатель устанавливает идеальный объем данных для отправки в каждом пакете, используя опцию / поле TCP Window. Получатель объявляет отправителю сколько данных он может получить в каждом пакете ACK, который соответствует свободное пространство буфера для сокета (SO_RCVBUF) и по умолчанию составляет 65535 байт.
Верхний предел отправителя является объявленным окном получателя. Отправитель не должен отправлять больше неиспользованных данных, чем это ограничение, иначе это приведет к переполнению буфера, в результате чего получатель отбросит дополнительные пакеты.
Окно перегрузки - это управление потоком, которое динамически настраивается на пропускную способность и надежность сети. Окно перегрузки запускает окно, в два раза превышающее максимальный размер сегмента. Он увеличивается механизмом медленного запуска TCP на каждом ACKed-пакете на 1. С этим алгоритмом окно перегрузки фактически удваивается для каждого времени прохождения туда-обратно.
По достижении порога медленного старта TCP переходит от использования алгоритма медленного старта к алгоритму предотвращения скопления. Окно увеличивается на 1 сегмент за каждое путешествие туда и обратно.