Компьютерные сети, протоколы и модель взаимодействия

Как сообщение из вашего браузера долетает до сервера на другом континенте за доли секунды — по строгим правилам.

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

Зачем это нужно

Интернет — крупнейшая инженерная система в истории, и она работает потому, что миллиарды устройств соблюдают общие правила — протоколы. Понимание того, как данные путешествуют по сети, демистифицирует всё: почему сайт открывается по имени, а не по числам; что такое «пакет»; зачем нужен TCP. Это основа сетевых технологий в школьной программе и фундамент любой работы с интернетом. Разберёмся в главных идеях наглядно.

Самое поразительное в интернете — что у него нет «главного компьютера», нет центра, который всем управляет. Это сеть из множества независимых устройств и сетей, которые договорились общаться по единым правилам. Никто не владеет интернетом целиком, и тем не менее ваше сообщение надёжно доходит до сервера на другом конце планеты, проходя по пути через десятки чужих устройств, каждое из которых лишь передаёт его дальше. Как такая «анархия» работает без сбоев? Секрет — в продуманной системе протоколов, которая разбивает сложную задачу связи на простые, независимые слои. Эта идея — разделение огромной проблемы на слои, каждый из которых решает свою узкую задачу и не вникает в детали других, — одна из самых мощных в инженерии вообще. Поняв её на примере сетей, вы научитесь видеть её и в других системах. Поэтому урок не столько про заучивание аббревиатур, сколько про понимание изящной архитектуры, благодаря которой интернет вообще существует.

Данные путешествуют пакетами

Большое сообщение не отправляют целиком — его режут на пакеты: небольшие порции с адресом получателя и номером. Пакеты летят по сети независимо, возможно разными путями, и собираются у получателя по номерам. Это надёжно: если пакет потерялся, переслать нужно только его, а не всё сообщение. Промоделируем «нарезку» и сборку:

message = "Привет, это тестовое сообщение для сети!"
packet_size = 10

# нарезаем на пакеты с номерами
packets = []
for i in range(0, len(message), packet_size):
    chunk = message[i:i + packet_size]
    packets.append((i // packet_size, chunk))   # (номер, данные)

print("Отправляем пакеты:")
for num, data in packets:
    print(f"  пакет #{num}: '{data}'")

# пакеты пришли вперемешку — собираем по номерам
import random
random.seed(5)
shuffled = packets[:]
random.shuffle(shuffled)
restored = "".join(data for num, data in sorted(shuffled))
print("\nСобрано у получателя:", restored)
print("совпало с исходным:", restored == message)

Вывод:

Отправляем пакеты:
  пакет #0: 'Привет, эт'
  пакет #1: 'о тестовое'
  пакет #2: ' сообщение'
  пакет #3: ' для сети!'

Собрано у получателя: Привет, это тестовое сообщение для сети!
совпало с исходным: True

Стек протоколов TCP/IP: разделение труда

Сетевое взаимодействие устроено слоями, и каждый слой решает свою задачу, опираясь на нижний. Это как почта: вы пишете письмо (содержание), кладёте в конверт с адресом (доставка), почта везёт его машинами (физическая передача). В сетях эту идею воплощает стек TCP/IP:

УровеньЧто делаетПримеры
Прикладнойработа приложенийHTTP, HTTPS, SMTP, DNS
Транспортныйнадёжная доставка, порядок пакетовTCP, UDP
Сетевой (межсетевой)адресация и маршрутизацияIP
Канальный/физическийпередача сигналов по средеEthernet, Wi-Fi

Ключевая пара — TCP и IP. IP отвечает за адреса и доставку пакетов «как получится». TCP поверх него гарантирует, что данные дойдут полностью и в правильном порядке: нумерует пакеты, переспрашивает потерянные, подтверждает получение. Для видеозвонков, где важнее скорость, чем стопроцентная точность, используют более простой UDP без переспрашивания.

DNS: имена вместо чисел

Компьютеры адресуют друг друга числами (IP-адресами), но человеку удобнее имена. DNS (служба доменных имён) — это «телефонная книга интернета», переводящая codechick.io в числовой адрес. Промоделируем работу DNS обычным словарём — по сути, так она и устроена:

# упрощённая DNS-таблица: имя -> IP
dns = {
    "codechick.io":   "185.199.108.153",
    "example.com":    "93.184.216.34",
    "school.local":   "192.168.1.10",
}

def resolve(name):
    return dns.get(name, "адрес не найден")

for site in ("codechick.io", "example.com", "unknown.site"):
    print(f"{site:<16} -> {resolve(site)}")

Вывод:

codechick.io     -> 185.199.108.153
example.com      -> 93.184.216.34
unknown.site     -> адрес не найден

Что происходит при открытии сайта

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

  1. DNS-запрос: имя сайта превращается в IP-адрес.
  2. Установка TCP-соединения с сервером по этому адресу (порт 443 для HTTPS).
  3. HTTP-запрос: браузер просит нужную страницу.
  4. Ответ сервера: страница приходит пакетами, TCP собирает их по порядку.
  5. Отрисовка: браузер показывает страницу.

Разберём структуру веб-адреса (URL) — в нём закодировано всё нужное для запроса:

url = "https://codechick.io/tutorials/python?level=10#start"

# грубый разбор URL на составные части
scheme, rest = url.split("://", 1)
host_path = rest.split("#", 1)[0]          # отбросили якорь
host_query = host_path.split("?", 1)
host_and_path = host_query[0]
query = host_query[1] if len(host_query) > 1 else ""
host = host_and_path.split("/", 1)[0]
path = "/" + host_and_path.split("/", 1)[1] if "/" in host_and_path else "/"

print("протокол:", scheme)
print("хост:    ", host)
print("путь:    ", path)
print("параметры:", query)

Вывод:

протокол: https
хост:     codechick.io
путь:     /tutorials/python
параметры: level=10

Попробуй сам

Смоделируем надёжность TCP: при передаче часть пакетов «теряется», и протокол их перепосылает, пока не дойдут все. Меняйте вероятность потери и число пакетов.

import random
random.seed(2)

total_packets = 8
loss_prob = 0.3        # вероятность потери пакета

delivered = set()
attempts = 0
while len(delivered) < total_packets:
    attempts += 1
    for p in range(total_packets):
        if p in delivered:
            continue
        if random.random() >= loss_prob:   # пакет дошёл
            delivered.add(p)

print("пакетов всего:", total_packets)
print("раундов передачи (с переотправкой):", attempts)
print("в итоге доставлены все:", len(delivered) == total_packets)

Вывод:

пакетов всего: 8
раундов передачи (с переотправкой): 2
в итоге доставлены все: True

Частые ошибки

  • Путают IP и DNS. IP — это числовой адрес, DNS — служба, переводящая имя в этот адрес.
  • Считают, что пакеты идут по порядку. Они летят независимо и могут прийти вперемешку; порядок восстанавливает TCP по номерам.
  • Думают, что TCP и UDP взаимозаменяемы. TCP надёжен, но медленнее; UDP быстр, но без гарантий — каждый для своих задач.
  • Смешивают протоколы разных уровней. HTTP работает поверх TCP, а тот — поверх IP; это слои, а не альтернативы.

Итоги

  • Данные передаются пакетами с номерами; получатель собирает сообщение по порядку.
  • Стек TCP/IP делит работу на слои: приложения, транспорт (TCP/UDP), сеть (IP), физическая передача.
  • IP адресует и доставляет пакеты, TCP гарантирует полноту и порядок, UDP — быстрая доставка без гарантий.
  • DNS переводит понятные имена сайтов в числовые IP-адреса.
Проверьте себя
1. Зачем большое сообщение в сети разбивают на пакеты?
AЧтобы оно занимало меньше места
BЧтобы пакеты шли независимо и при потере пересылать только потерянный, а не всё сообщение
CЧтобы зашифровать данные
DЭто требование браузера
2. За что отвечает протокол TCP в стеке TCP/IP?
AЗа числовую адресацию устройств
BЗа надёжную доставку данных в правильном порядке
CЗа перевод имён сайтов в IP-адреса
DЗа передачу сигналов по кабелю
3. Что делает служба DNS?
AШифрует трафик
BПереводит доменное имя сайта в числовой IP-адрес
CРазбивает сообщение на пакеты
DУскоряет соединение
Поддержать проект