Перейти до основного вмісту

TCP/IP

TCP/IP — це набір мережевих протоколів, на основі якого працює сучасний Інтернет. Коли браузер відкриває сайт, Java-застосунок звертається до REST API, сервер встановлює з'єднання з базою даних або один мікросервіс викликає інший — у більшості випадків десь під капотом працюють протоколи TCP/IP.

Назва TCP/IP походить від двох найвідоміших протоколів цього стеку:

  • TCP (Transmission Control Protocol) — забезпечує надійну передачу потоку даних між двома кінцевими точками;
  • IP (Internet Protocol) — відповідає за адресацію вузлів та доставку IP-пакетів між мережами.

При цьому TCP та IP — лише частина великого набору протоколів. Наприклад, DNS використовується для перетворення доменних імен на IP-адреси, HTTP — для передачі веб-запитів, TLS — для шифрування, UDP — для швидкої передачі дейтаграм без гарантії доставки.

Щоб зрозуміти, як усе це працює разом, потрібно розібратися з мережевою моделлю та рівнями TCP/IP.

Що таке мережевий протокол

Мережевий протокол — це набір правил, за якими різні пристрої обмінюються даними.

Наприклад, якщо один комп'ютер хоче передати іншому число 100, недостатньо просто фізично передати кілька байтів. Потрібно домовитися:

  • як визначити отримувача;
  • як визначити відправника;
  • як розділити дані на частини;
  • як зрозуміти, що дані пошкоджені;
  • як повторно відправити загублені дані;
  • як визначити, якому застосунку призначені отримані дані.

Саме для вирішення цих задач існують різні мережеві протоколи.

Модель TCP/IP

Класична модель TCP/IP складається з чотирьох рівнів:

  1. Application — прикладний;
  2. Transport — транспортний;
  3. Internet — мережевий;
  4. Link / Network Access — канальний або рівень доступу до мережі.

Іноді використовують п'ятирівневу навчальну модель, де канальний рівень розділяють на:

  • Data Link;
  • Physical.

Це нагадує OSI-модель із семи рівнями, але TCP/IP та OSI — не одне й те саме.

Зручно уявляти передачу приблизно так:

Application -> Transport -> Internet -> Link -> Physical medium

Наприклад, Java-програма формує HTTP-запит. HTTP знаходиться на прикладному рівні. HTTP використовує TCP, TCP використовує IP, а IP працює поверх Ethernet або Wi-Fi.

1. Прикладний рівень (Application Layer)

Це найвищий рівень, з яким безпосередньо взаємодіють прикладні програми.

До протоколів цього рівня належать:

  • HTTP;
  • HTTPS;
  • DNS;
  • SMTP;
  • IMAP;
  • SSH;
  • FTP;
  • WebSocket;
  • та багато інших.

Приклад HTTP-запиту:

GET /users/10 HTTP/1.1 
Host: example.com 
Accept: application/json

Цей текст сам по собі не знає нічого про TCP-сегменти, IP-адреси або Ethernet-кадри.

Для Java-розробника типовий приклад — HTTP-клієнт:

HttpClient client = HttpClient.newHttpClient(); 
HttpRequest request = HttpRequest.newBuilder() 
    .uri(URI.create("https://example.com")) 
    .GET() 
    .build(); 
HttpResponse<String> 
response = client.send( request, HttpResponse.BodyHandlers.ofString() ); 
System.out.println(response.statusCode()); 
System.out.println(response.body());

З точки зору Java ми працюємо з HTTP-клієнтом. Але під ним відбувається набагато більше.

Що відбувається під час HTTP-запиту

Умовно ланцюжок виглядає так:

Java application -> HTTP -> TLS -> TCP -> IP -> Ethernet / Wi-Fi -> Network interface -> Internet

Важливий момент: не кожен протокол у реальній системі можна ідеально помістити в одну комірку моделі. Наприклад, TLS часто розглядають як проміжний рівень між application та transport.

DNS

Коли застосунок звертається до:

https://api.example.com

йому спочатку потрібно дізнатися IP-адресу сервера.

DNS виконує перетворення на кшталт:

api.example.com -> 203.0.113.20

DNS найчастіше працює через UDP, але в певних сценаріях може використовувати TCP, а сучасні варіанти DNS можуть працювати поверх TLS або HTTPS.

2. Транспортний рівень

Транспортний рівень відповідає за взаємодію між процесами на кінцевих вузлах.

Основні протоколи:

  • TCP;
  • UDP;
  • у сучасних системах також важливу роль відіграє QUIC, який реалізує транспортні механізми поверх UDP.

Одне з головних понять цього рівня — порт.

Що таке порт

IP-адреса дозволяє визначити вузол, але на одному комп'ютері можуть одночасно працювати сотні програм.

Наприклад:

192.168.1.10:8080 
192.168.1.10:5432 
192.168.1.10:22

IP-адреса визначає хост, а порт дозволяє визначити конкретну мережеву кінцеву точку.

Наприклад:

  • 22 — SSH;
  • 53 — DNS;
  • 80 — HTTP;
  • 443 — HTTPS;
  • 5432 — типовий порт PostgreSQL.

Не слід сприймати номер порту як «порт на мережевій карті». Це логічний ідентифікатор процесу або мережевої служби.

TCP

TCP — connection-oriented протокол. Перед передачею даних між двома сторонами він встановлює логічне з'єднання.

Основні властивості TCP:

  • надійна доставка;
  • збереження порядку байтів;
  • контроль потоку;
  • контроль перевантаження мережі;
  • виявлення втрат;
  • повторна передача втрачених сегментів.

При цьому важливо розуміти: TCP гарантує надійний байтовий потік, але не зберігає межі повідомлень.

Наприклад, якщо програма відправила:

HELLO WORLD

отримувач не зобов'язаний отримати це двома окремими повідомленнями. Він може отримати:

HELLOWORLD

або:

HEL LOWO RLD

Тому протоколи прикладного рівня повинні самі визначати межі повідомлень. HTTP, наприклад, має власну структуру заголовків і тіла.

TCP three-way handshake

Перед передачею даних TCP зазвичай встановлює з'єднання за допомогою three-way handshake.

Client Server SYN ------------------------> <------------------ SYN + ACK ACK ------------------------> Connection established

SYN означає, що клієнт хоче встановити з'єднання.

SYN + ACK означає, що сервер отримав запит і підтверджує його.

ACK завершує процес встановлення.

Sequence Number та Acknowledgment Number

TCP нумерує байти потоку. Це дозволяє визначати:

  • які дані вже отримані;
  • які дані загубилися;
  • у якому порядку потрібно відновити потік.

Наприклад, умовно:

Segment 1: Sequence = 1000 Data = 500 bytes 
Segment 2: Sequence = 1500 Data = 500 bytes

Якщо отримувач уже отримав перші 1000 байтів, він може повідомити відправнику, що очікує дані, починаючи з певного sequence number.

TCP ACK

ACK дозволяє підтверджувати отримання даних.

Наприклад:

Client -> Server: bytes 1000-1499 
Server -> Client: ACK 1500

У спрощеному вигляді це означає: «я отримав усе до байта перед позицією 1500 і очікую наступні дані».

Що відбувається при втраті пакета

IP не гарантує доставку. Пакет може бути втрачений через перевантаження, проблеми на каналі, переповнення буфера маршрутизатора або інші причини.

TCP виявляє проблему та виконує повторну передачу.

Client Server DATA ------------------> X lost <----------- ACK / duplicate ACK DATA ------------------> retransmission

Таким чином, на рівні TCP виникає надійний потік, хоча нижча мережа може втрачати окремі пакети.

Контроль потоку

TCP має flow control — механізм, який дозволяє отримувачу повідомляти, скільки даних він готовий прийняти.

Для цього використовується receive window.

Умовно:

Receiver: "I can currently accept 64 KB more data."

Відправник не повинен безмежно накопичувати дані в мережі.

Це важливо, коли один вузол працює швидше за інший.

Контроль перевантаження

Flow control та congestion control — різні речі.

Flow control захищає отримувача.

Congestion control захищає мережу.

У TCP існують алгоритми керування перевантаженням, зокрема механізми, пов'язані з:

  • slow start;
  • congestion avoidance;
  • fast retransmit;
  • fast recovery.

Загальна ідея полягає в тому, що TCP не повинен відправляти дані з максимально можливою швидкістю незалежно від стану мережі.

TCP FIN і завершення з'єднання

З'єднання TCP завершується окремим процесом, який часто описують як four-way termination.

Client Server FIN --------------------------> <---------------------- ACK <---------------------- FIN ACK -------------------------->

У TCP можуть існувати різні стани, серед яких:

CLOSED 
LISTEN 
SYN-SENT 
SYN-RECEIVED 
ESTABLISHED 
FIN-WAIT-1 
FIN-WAIT-2 
CLOSE-WAIT 
CLOSING 
LAST-ACK 
TIME-WAIT

Найвідоміший для практичної діагностики стан — TIME_WAIT. Він потрібен, зокрема, для коректного завершення старого з'єднання та запобігання змішуванню старих сегментів із новим з'єднанням.

UDP

UDP (User Datagram Protocol) набагато простіший за TCP.

UDP не гарантує:

  • доставку;
  • порядок доставки;
  • відсутність дублювання;
  • повторну передачу.

При цьому UDP має важливі переваги: менше накладних витрат, відсутність встановлення TCP-з'єднання та можливість самостійно реалізувати потрібну логіку поверх нього.

UDP використовується, наприклад, у:

  • DNS;
  • мережевих іграх;
  • VoIP;
  • відео- та аудіопотоках;
  • DHCP;
  • QUIC/HTTP/3.

TCP і UDP: головна різниця

Властивість TCP UDP
З'єднання Так Ні
Надійність Так Ні
Порядок даних Гарантується Не гарантується
Retransmission Є Немає
Flow control Є Немає в протоколі UDP
Congestion control Є Немає в самому UDP

Java та TCP

У Java безпосередньо працювати з TCP можна через Socket та ServerSocket.

Простий сервер:

try (ServerSocket serverSocket = new ServerSocket(8080)) { 
    try (Socket socket = serverSocket.accept()) { 
        BufferedReader reader = new BufferedReader( new InputStreamReader(socket.getInputStream()) ); 
        PrintWriter writer = new PrintWriter( socket.getOutputStream(), true ); 
        String message = reader.readLine(); 
        System.out.println("Received: " + message); writer.println("Hello from server"); } }

Клієнт:

try (Socket socket = new Socket("localhost", 8080)) { 
    BufferedReader reader = new BufferedReader( new InputStreamReader(socket.getInputStream()) ); 
    PrintWriter writer = new PrintWriter( socket.getOutputStream(), true ); 
    writer.println("Hello server"); 
    String response = reader.readLine(); 
    System.out.println(response); }

Тут Java працює безпосередньо з TCP-сокетом.

Що таке socket

У практичному сенсі socket — це програмний інтерфейс, через який застосунок взаємодіє з мережевим стеком операційної системи.

Для TCP з'єднання можна концептуально представити як:

Source IP + Source Port + Destination IP + Destination Port + TCP

Наприклад:

192.168.1.10:52341 -> 93.184.216.34:443 TCP

Така комбінація визначає конкретне TCP-з'єднання.

3. Мережевий рівень (Internet Layer)

На цьому рівні працює IP.

Основна задача IP — доставити пакет від одного вузла до іншого через одну або декілька мереж.

Найпоширеніші версії:

  • IPv4;
  • IPv6.

IPv4

IPv4 використовує 32-бітну адресу.

Наприклад:

192.168.1.100

У двійковому вигляді це 32 біти:

11000000.10101000.00000001.01100100

Теоретично існує приблизно 4,3 мільярда IPv4-адрес, але на практиці доступний глобальний адресний простір значно складніший через спеціальні діапазони, резервування та інші механізми.

Приватні IP-адреси

У локальних мережах часто використовуються приватні адреси.

Основні діапазони IPv4:

10.0.0.0/8 172.16.0.0/12 192.168.0.0/16

Наприклад:

192.168.1.10

така адреса може існувати одночасно в тисячах різних локальних мереж.

IPv6

IPv6 використовує 128-бітні адреси.

Приклад:

2001:db8:abcd:0012:0000:0000:0000:0001

IPv6 має величезний адресний простір і вирішує проблему обмеженої кількості IPv4-адрес.

Subnet mask та CIDR

IP-адреса не просто вказує номер пристрою. Вона також пов'язана з інформацією про мережу.

Наприклад:

192.168.1.10/24

Запис /24 означає, що перші 24 біти належать до мережевої частини адреси.

Для 192.168.1.10/24 мережа буде:

192.168.1.0/24

а типові адреси в цій мережі знаходяться в межах:

192.168.1.1 ... 192.168.1.254

У сучасних мережах використовується CIDR — Classless Inter-Domain Routing, що дозволяє гнучко задавати розмір мережі.

Default Gateway

Якщо комп'ютер хоче звернутися до іншої мережі, він зазвичай передає трафік маршрутизатору — default gateway.

Наприклад:

PC 192.168.1.10 | | default gateway v 192.168.1.1 | v Internet

Якщо сервер має адресу 8.8.8.8, а клієнт знаходиться в мережі 192.168.1.0/24, пакет не надсилається безпосередньо на 8.8.8.8 через Ethernet. Він передається локальному маршрутизатору, який далі маршрутизує його.

Маршрутизація

Router аналізує IP-пакет і вирішує, куди його передати далі.

Умовно:

Client | v Router A | v Router B | v Router C | v Server

Кожен маршрутизатор не обов'язково знає повний шлях від джерела до призначення. Він використовує таблицю маршрутизації та вибирає наступний крок.

Routing table

У Linux таблицю маршрутів можна подивитися, наприклад, так:

ip route

Типовий результат може виглядати приблизно так:

default via 192.168.1.1 dev eth0 
192.168.1.0/24 dev eth0 proto kernel scope link 

Перший рядок означає: для мереж, для яких немає більш конкретного маршруту, використовувати gateway 192.168.1.1.

TTL

IPv4 має поле TTL (Time To Live).

Воно зменшується маршрутизаторами. Якщо TTL досягає нуля, пакет відкидається.

Це потрібно, щоб пакет не міг нескінченно циркулювати мережею через помилку маршрутизації.

Саме з TTL пов'язаний принцип роботи команди:

traceroute example.com

або:

traceroute example.com 

Програма поступово змінює TTL і за відповідями визначає проміжні маршрутизатори.

IP не гарантує доставку

Це одна з найважливіших концепцій.

IP — це переважно best-effort protocol.

IP намагається доставити пакет, але не обіцяє:

  • що пакет буде доставлений;
  • що він буде доставлений лише один раз;
  • що пакети прийдуть у правильному порядку;
  • що відправнику буде повідомлено про втрату.

Надійність, якщо вона потрібна, забезпечується вищим рівнем, наприклад TCP.

IPv4 packet

IP-пакет містить заголовок та дані.

У заголовку є, серед іншого:

  • source IP;
  • destination IP;
  • TTL;
  • protocol;
  • length;
  • інформація про фрагментацію.

Поле Protocol дозволяє IP зрозуміти, який протокол знаходиться вище.

Наприклад, для IPv4 типове значення:

6 -> TCP 
17 -> UDP 
1 -> ICMP

4. Канальний рівень (Link Layer)

На цьому рівні дані передаються безпосередньо в межах конкретної мережевої технології.

Приклади:

  • Ethernet;
  • Wi-Fi;
  • PPP;
  • інші технології канального доступу.

Якщо IP говорить: «потрібно доставити пакет на адресу 192.168.1.20», канальний рівень повинен вирішити, як доставити його до наступного вузла в конкретній локальній мережі.

MAC-адреса

На Ethernet та Wi-Fi використовується MAC-адреса.

Приклад:

3c:52:82:ab:12:34

MAC-адреса та IP-адреса — різні речі.

IP використовується для логічної адресації та маршрутизації між мережами.

MAC використовується для доставки кадрів у межах конкретного канального сегмента.

ARP

У IPv4 для визначення MAC-адреси за локальною IP-адресою використовується ARP (Address Resolution Protocol).

Наприклад, комп'ютер хоче відправити дані на:

192.168.1.20

Але для Ethernet йому потрібна MAC-адреса.

Він може відправити широкомовний ARP-запит:

Who has 192.168.1.20?

Пристрій із відповідною IP-адресою відповідає приблизно:

192.168.1.20 is at 3c:52:82:ab:12:34

Після цього IP-пакет можна помістити в Ethernet-кадр і передати в локальній мережі.

Ethernet frame

Канальний рівень передає не IP-пакети безпосередньо, а кадри.

У спрощеному вигляді Ethernet frame містить:

+---------------------+ | Destination MAC | +---------------------+ | Source MAC | +---------------------+ | EtherType | +---------------------+ | Payload | +---------------------+ | FCS | +---------------------+

Payload може містити IP-пакет.

Ієрархія інкапсуляції

Одна з найважливіших ідей TCP/IP — encapsulation.

Кожен нижчий рівень додає свій заголовок.

Умовно:

HTTP data -> [TCP header][HTTP data] -> [IP header][TCP header][HTTP data] -> [Ethernet header][IP header][TCP header][HTTP data][FCS]

На стороні отримувача відбувається зворотний процес — decapsulation.

Ethernet frame -> IP packet -> TCP segment -> Application data

Термінологія: segment, packet, frame

Залежно від рівня використовуються різні назви.

  • Application data — дані прикладного протоколу;
  • TCP segment — одиниця передачі TCP;
  • UDP datagram — одиниця передачі UDP;
  • IP packet — IP-пакет;
  • Ethernet frame — кадр Ethernet.

У повсякденній мові всі ці речі часто називають просто «пакетами», але технічно це не зовсім правильно.

MTU

MTU (Maximum Transmission Unit) — максимальний розмір IP-пакета, який може передати певний мережевий інтерфейс без фрагментації на конкретному каналі.

Для стандартного Ethernet типовим значенням є:

1500 bytes

Це важливий параметр, оскільки до IP-пакета додаються TCP або UDP заголовки, а дані прикладного рівня повинні вписатися у доступний простір.

MSS

Для TCP важливим поняттям є MSS (Maximum Segment Size).

Якщо MTU дорівнює 1500 байтів, то для звичайного IPv4 без додаткових опцій:

MTU = 1500 IPv4 header = 20 TCP header = 20 MSS ≈ 1500 - 20 - 20 MSS ≈ 1460 bytes

Тобто TCP-дані в одному сегменті можуть мати приблизно 1460 байтів.

На практиці все складніше через TCP/IP options, IPv6, тунелювання, VPN тощо.

NAT

NAT (Network Address Translation) використовується для зміни мережевих адрес при проходженні трафіку через маршрутизатор.

Найвідоміший варіант — PAT, коли багато локальних клієнтів використовують одну публічну IPv4-адресу.

Наприклад:

192.168.1.10:50000 192.168.1.11:50001 192.168.1.12:50002 | v Router/NAT | v 203.0.113.10

Маршрутизатор підтримує таблицю відповідностей і може розрізняти з'єднання за портами.

Що реально відбувається, коли Java-клієнт викликає HTTPS API

Розглянемо типовий запит:

https://api.example.com/users

У спрощеному вигляді відбуваються такі кроки.

1. DNS resolution.

api.example.com -> 203.0.113.10

2. Створення TCP-з'єднання.

Client: ephemeral port -> 52341 
Server: port -> 443

Відбувається TCP handshake.

3. Встановлення TLS.

Для HTTPS поверх TCP встановлюється захищений TLS-канал.

4. Передача HTTP.

GET /users HTTP/1.1 Host: api.example.com

5. TCP розбиває потік на сегменти.

6. IP додає source та destination IP.

7. Ethernet або Wi-Fi формує кадри.

8. Маршрутизатори пересилають пакети.

На сервері відбувається зворотний процес.

Логічна схема повного шляху

Java Application | v HTTP | v TLS | v TCP | v IPv4 / IPv6 | v Ethernet / Wi-Fi | v Router | v Internet | v Server Network Interface | v IP | v TCP | v TLS | v HTTP | v Java Application

TCP/IP та OSI

Для навчання часто порівнюють TCP/IP та OSI.

OSI TCP/IP Приклади
Application Application HTTP, DNS, SMTP, SSH
Presentation TLS, кодування, серіалізація
Session логіка сесій
Transport Transport TCP, UDP
Network Internet IP, ICMP
Data Link Link Ethernet, Wi-Fi, ARP
Physical кабель, радіосигнал

OSI корисна як концептуальна модель, але реальні мережі будуються навколо конкретних протоколів і стеків, а не навколо абстрактних рівнів OSI.

Що відбувається при передачі даних між двома комп'ютерами

Уявімо:

Computer A 192.168.1.10 | | Internet | Computer B 203.0.113.20

Java-програма на Computer A робить:

socket.connect( new InetSocketAddress("203.0.113.20", 443) );

Java передає запит операційній системі.

ОС формує TCP-сегмент.

TCP додає:

source port destination port sequence number acknowledgment number flags window checksum

Потім IP додає:

source IP destination IP TTL protocol

Після цього канальний рівень додає MAC-адреси для передачі до наступного вузла.

Це важлива деталь: MAC-адреса не подорожує через весь Інтернет разом із початковим IP-пакетом. При переході через маршрутизатор Ethernet-кадр зазвичай змінюється для кожного нового канального сегмента, тоді як source/destination IP залишаються адресами кінцевих вузлів, за винятком механізмів на кшталт NAT.

Що може змінюватися під час проходження мережі

У процесі проходження мережі різні поля можуть мати різну поведінку.

Ethernet MAC — зазвичай змінюється на кожному L2-сегменті.

IP TTL — зменшується на маршрутизаторах.

Source/Destination IP — зазвичай зберігаються, але можуть змінюватися через NAT.

TCP source/destination port — зазвичай зберігаються, але NAT/PAT може змінювати source port.

ICMP

ICMP (Internet Control Message Protocol) використовується для службових повідомлень на мережевому рівні.

Наприклад, команда:

ping 8.8.8.8

зазвичай використовує ICMP Echo Request та ICMP Echo Reply.

Тому ping не є тестом TCP. Сервер може блокувати ICMP і при цьому нормально приймати TCP-з'єднання на порт 443.

Як подивитися TCP/IP у Linux

Для розробника дуже корисно вміти дивитися не лише Java-код, а й реальний мережевий стан системи.

IP-адреси інтерфейсів:

ip addr

Маршрути:

ip route

Список TCP-з'єднань:

ss -t

Слухаючі TCP-порти:

ss -lnt

Слухаючі TCP та UDP порти:

ss -lntup

Перевірка DNS:

dig example.com

Перевірка доступності вузла:

ping example.com

Перегляд маршруту:

traceroute example.com

Wireshark та tcpdump

Коли потрібно побачити реальний TCP/IP-трафік, використовують packet capture інструменти.

Наприклад:

sudo tcpdump -i any port 8080

Або Wireshark, який дозволяє аналізувати:

  • Ethernet frames;
  • IP packets;
  • TCP segments;
  • UDP datagrams;
  • DNS;
  • HTTP;
  • TLS handshake;
  • retransmissions;
  • TCP flags;
  • latency та багато іншого.

Наприклад, можна побачити TCP handshake:

SYN SYN, ACK ACK

а потім:

PSH, ACK ACK PSH, ACK ACK FIN, ACK ACK

TCP flags

До основних TCP flags належать:

  • SYN — встановлення з'єднання;
  • ACK — підтвердження;
  • FIN — коректне завершення;
  • RST — аварійне скидання з'єднання;
  • PSH — прохання передати дані вище по стеку без зайвої затримки буферизації;
  • URG — historically пов'язаний з urgent data.

Для практичної діагностики особливо важливі SYN, ACK, FIN та RST.

Що означає Connection Refused

Якщо Java-програма отримує щось на кшталт:

java.net.ConnectException: Connection refused

це принципово відрізняється від timeout.

Connection refused зазвичай означає, що клієнт зміг дійти до вузла, але TCP-з'єднання було відхилене, часто через відсутність процесу, який слухає цей порт, або через активне скидання з'єднання.

Наприклад:

localhost:8080

але жоден процес не слухає 8080.

Перевірити:

ss -lntp | grep 8080

Що означає timeout

При timeout ситуація інша.

Наприклад:

java.net.SocketTimeoutException

Причин може бути багато:

  • сервер недоступний;
  • пакети губляться;
  • firewall мовчки відкидає трафік;
  • маршрут зламаний;
  • сервер занадто повільно відповідає.

TCP та HTTP — це не одне й те саме

Це дуже поширена помилка початківців.

HTTP — прикладний протокол.

TCP — транспортний протокол.

Наприклад:

HTTP -> TCP -> IP -> Ethernet

HTTP не займається retransmission TCP-сегментів. TCP не знає, що в його байтах знаходиться HTTP.

Для TCP це просто потік байтів.

HTTPS — це теж не окремий транспортний протокол

HTTPS — це по суті HTTP, переданий через захищений TLS-канал.

Типовий стек HTTP/1.1 або HTTP/2:

HTTP TLS TCP IP Ethernet

Для HTTP/3 ситуація інша:

HTTP/3 QUIC UDP IP Ethernet

Тобто HTTP/3 принципово відрізняється від HTTP/1.1 та HTTP/2 за транспортною основою.

QUIC і сучасний Інтернет

QUIC використовує UDP як основу, але реалізує поверх нього механізми, які традиційно асоціюються з транспортним протоколом:

  • надійну передачу;
  • контроль перевантаження;
  • шифрування;
  • multiplexing;
  • швидше встановлення з'єднання.

Саме QUIC є основою HTTP/3.

Тому сучасну веб-архітектуру вже не можна повністю описувати просто як:

HTTP → TCP → IP

Все частіше зустрічається:

HTTP/3 → QUIC → UDP → IP

Поняття latency, bandwidth та throughput

Для мереж дуже важливо розрізняти ці поняття.

Latency — затримка передачі.

Bandwidth — теоретична пропускна здатність каналу.

Throughput — фактична швидкість передачі даних.

Наприклад, канал може мати:

Bandwidth = 1 Gbit/s

але через latency, втрати пакетів, congestion, TCP window, CPU та інші фактори реальний throughput між двома серверами може бути набагато нижчим.

TCP window та bandwidth-delay product

На великих відстанях важлива не лише пропускна здатність каналу, а й час проходження даних.

Умовно:

Bandwidth = 1 Gbit/s RTT = 100 ms

Щоб повністю завантажити канал, TCP може потребувати значного обсягу даних «у польоті».

Це пов'язано з поняттям Bandwidth-Delay Product (BDP):

BDP = Bandwidth × RTT

Наприклад:

1 Gbit/s × 0.1 s = 100 Mbit

Тобто для повного використання такого каналу може знадобитися близько 12,5 MB даних у польоті.

Чому TCP може бути «повільним»

Коли розробник бачить низьку швидкість передачі даних, проблема не обов'язково в Java.

Можливі причини:

  • високий RTT;
  • packet loss;
  • невелике TCP congestion window;
  • малий receive window;
  • MTU/PMTUD problems;
  • firewall;
  • NAT;
  • перевантажений канал;
  • повільний сервер;
  • повільна серіалізація або шифрування;
  • обмеження самого застосунку.

TCP та багатопоточність у Java

Наявність TCP-з'єднання не означає, що Java автоматично створює окремий потік на кожне з'єднання.

У класичних blocking-серверах часто використовувалася модель:

Client 1 -> Thread 1 
Client 2 -> Thread 2 
Client 3 -> Thread 3 ...

Сучасні системи можуть використовувати:

  • NIO;
  • epoll/kqueue;
  • event loops;
  • reactive programming;
  • virtual threads.

Наприклад, Spring WebFlux використовує неблокуючу модель, тоді як класичний Spring MVC часто працює на основі blocking I/O.

TCP у Spring Boot

Коли Java-розробник пише:

RestClient restClient = RestClient.create(); String response = restClient.get() .uri("https://example.com") .retrieve() .body(String.class);

він не працює з TCP безпосередньо. Мережевий стек прихований під рівнями HTTP-клієнта, TLS та socket API.

Це одна з переваг абстракції: application developer може працювати з HTTP, не формуючи вручну TCP segment.

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

Connection Pooling

Оскільки встановлення TCP-з'єднання має ціну, HTTP-клієнти часто використовують connection pooling.

Замість:

HTTP request ↓ TCP connect ↓ HTTP request ↓ TCP close

може використовуватися:

TCP connection | +--- HTTP request +--- HTTP request +--- HTTP request +--- HTTP request

Це значно зменшує накладні витрати.

Особливо це важливо для мікросервісів, де один сервіс може виконувати тисячі HTTP-викликів на інший.

Keep-Alive

HTTP/1.1 підтримує повторне використання TCP-з'єднань.

Це дозволяє уникати постійного:

TCP handshake -> HTTP request -> TCP close -> TCP handshake -> HTTP request -> TCP close

У сучасних системах повторне використання з'єднань є практично стандартною оптимізацією.

HTTP/2 та одне TCP-з'єднання

HTTP/2 дозволяє мультиплексувати декілька логічних потоків через одне TCP-з'єднання.

One TCP connection | +--- HTTP stream 1 +--- HTTP stream 2 +--- HTTP stream 3 +--- HTTP stream 4

Це значно зменшує кількість з'єднань.

Але TCP залишається byte-stream транспортом. HTTP/2 реалізує власний рівень фреймів і потоків поверх TCP.

TCP Head-of-Line Blocking

У TCP усі байти потоку повинні бути доставлені в правильному порядку.

Тому якщо один TCP-сегмент загубився, наступні дані можуть уже бути фізично доставлені мережою, але application-рівень не зможе повноцінно використати їх доти, доки TCP не відновить втрачені байти.

Це називається Head-of-Line Blocking.

QUIC має іншу модель потоків, яка дозволяє краще ізолювати окремі logical streams.

Чому знання TCP/IP важливе для Java-розробника

Навіть якщо ви не пишете мережеві драйвери та не працюєте з пакетами вручну, знання TCP/IP допомагає розуміти проблеми на практичному рівні.

Наприклад, воно допомагає пояснити:

  • чому отримуємо Connection refused;
  • чому виникає timeout;
  • чому API іноді повільно відповідає;
  • чому connection pool має значення;
  • чому після певної кількості запитів з'являються проблеми з портами;
  • чому NAT змінює поведінку з'єднання;
  • чому DNS може бути причиною проблеми;
  • чому один великий TCP stream працює не так, як багато UDP datagrams;
  • чому HTTP/2 і HTTP/3 працюють по-різному;
  • чому мережеві помилки можуть бути зовсім не пов'язані з Java-кодом.

Що варто запам'ятати

Application layer визначає, що саме хочуть передати програми. HTTP, DNS та SMTP — приклади протоколів цього рівня.

Transport layer забезпечує взаємодію між процесами. TCP дає надійний впорядкований потік байтів, а UDP — простий механізм передачі дейтаграм без гарантій доставки.

Internet layer займається логічною адресацією та маршрутизацією. Основний протокол — IP.

Link layer відповідає за передачу даних у конкретному каналі — наприклад Ethernet або Wi-Fi.

Головний принцип TCP/IP можна звести до інкапсуляції:

Application data -> TCP segment -> IP packet -> Ethernet frame -> Physical transmission

А на стороні отримувача все відбувається у зворотному напрямку.

Ментальна модель TCP/IP для щоденної роботи

Коли у Java-застосунку виникає мережева проблема, корисно рухатися знизу вгору:

1. Чи є network interface? 2. Чи є IP-адреса? 3. Чи правильний routing? 4. Чи доступний host? 5. Чи відкритий потрібний port? 6. Чи встановлюється TCP connection? 7. Чи проходить TLS? 8. Чи працює HTTP? 9. Чи коректна логіка application?

Наприклад, якщо:

curl https://example.com 

не працює, не варто одразу шукати помилку у Java-коді. Спочатку потрібно визначити, на якому саме рівні виникла проблема.

Висновок

TCP/IP — це не один протокол, а цілий стек протоколів, кожен рівень якого виконує свою задачу.

IP відповідає за логічну адресацію та маршрутизацію. TCP додає надійний впорядкований потік даних. UDP забезпечує мінімалістичну передачу дейтаграм. Ethernet та Wi-Fi відповідають за локальну передачу. HTTP, DNS, SSH та інші протоколи реалізують функціональність, яку безпосередньо використовують програми.

Коментарі

Популярні публікації

Дамп бази даних Postgresql локально

Що потрібно встановити локально (Ubuntu) Встанови клієнтські утиліти PostgreSQL: pg_dump , psql , pg_restore . sudo apt update sudo apt install postgresql-client Кроки міграції Ідея: не зберігати дамп на серверах. Зробити дамп з віддаленого сервера на свій локальний ПК, потім передати його на новий сервер і там відновити. 1) Створення дампу з віддаленого сервера локально pg_dump -h OLD_SERVER_IP -U OLD_USER -Fc -d OLD_DB -f dump_file.dump Пояснення ключів: -h (хост), -U (користувач), -Fc (custom format), -d (БД), -f (вихідний файл локально). 1.1) Варіант з розбиттям на частини (якщо треба) pg_dump -h OLD_SERVER_IP -U OLD_USER -Fc -d OLD_DB | split -b 10G - dump_file.dump.part_ Це створить локально файли типу dump_file.dump.part_aa , dump_file.dump.part_ab тощо. 2) Передача дампу на новий сервер Один файл: scp dump_file.dump NEW_USER@NEW_SERVER_IP:/tmp/ Або частинами: scp dump_file.dump.part_* NEW_USER@NEW_SERVER_IP:/tmp/ 3) Збирання файл...

Основи Next.js

Що таке Next.js? Next.js — це прогресивний фреймворк для розробки веб-застосунків на основі React. Він розширює можливості React, додаючи готову інфраструктуру для Server-Side Rendering (SSR), генерації статичних сторінок, маршрутизації через файлову систему, а також можливість створювати backend-ендпоінти прямо в проєкті. Чому він став популярним? Next.js швидко здобув популярність завдяки тому, що пропонує: SEO-дружні сторінки завдяки SSR / SSG; швидкий перший рендер (First Page Load); просту маршрутизацію без налаштування; розгортання в один клік через Vercel; вбудовану оптимізацію зображень та продуктивності. Чим відрізняється від класичного React У класичному React ми отримуємо лише клієнтську бібліотеку для побудови UI-компонентів. Усе інше (SSR, маршрути, API) треба налаштовувати вручну або через сторонні бібліотеки (наприклад, React Router, Redux, Express, etc.). Next.js — це уже повноцінний фреймворк. Він одразу має: серверний рендеринг...

ООП у TypeScript

Короткий вступ TypeScript додає статичну типізацію поверх JavaScript і підтримує класичні концепти ООП: класи , успадкування , інтерфейси , інкапсуляцію , поліморфізм та абстракції . Нижче — практичні приклади та пояснення. Класи — декларація, конструктор, властивості та методи class Person { public name: string; private age: number; protected email?: string; // необов’язкове static species = 'Homo sapiens'; constructor(name: string, age: number, email?: string) { this.name = name; this.age = age; this.email = email; } public greet(): string { return `Hi, I'm ${this.name}.`; } private getBirthYear(currentYear: number): number { return currentYear - this.age; } } const p = new Person('Ivan', 30, 'ivan@example.com'); console.log(p.greet()); // console.log(p.age); // помилка: 'age' приватне console.log(Person.species); Успадкування і перевизначення (extends, super) class Employee extends Person { ...

Створення проєкту на TypeScript, модулі

Крок 1. Ініціалізація проєкту Спочатку створимо нову теку та ініціалізуємо Node.js-проєкт за допомогою npm : mkdir my-typescript-app cd my-typescript-app npm init -y Крок 2. Встановлення TypeScript Додаємо TypeScript як dev-залежність: npm install --save-dev typescript ts-node @types/node - typescript — компілятор TypeScript - ts-node — дозволяє запускати TS-файли без попередньої компіляції - @types/node — типи для стандартних Node.js API Крок 3. Створення файлу tsconfig.json Ініціалізуємо конфігурацію TypeScript: npx tsc --init Приклад файлу tsconfig.json { "compilerOptions": { "target": "ES2020", // Версія JS у вихідному коді "module": "CommonJS", // Система модулів (для Node.js) "rootDir": "src", // Вхідна папка з TypeScript-кодом "outDir": "dist", // Куди компілюється код JS "str...

Інструменти для роботи з Node.js

Що таке npm? npm (Node Package Manager) — це офіційний пакетний менеджер для Node.js . Він дозволяє: Встановлювати сторонні бібліотеки та фреймворки Керувати залежностями проєкту Запускати скрипти (команди) через package.json Приклад ініціалізації проєкту з npm npm init -y Файл package.json (скорочений приклад) { "name": "my-project", "version": "1.0.0", "scripts": { "start": "ts-node src/index.ts", "build": "tsc" }, "dependencies": { "express": "^4.18.0" }, "devDependencies": { "typescript": "^5.0.0", "ts-node": "^10.0.0" } } Що таке tsconfig.json? tsconfig.json — це файл конфігурації для компілятора TypeScript, який визначає, як слід компілювати код. Приклад файлу tsconfig.json { "compilerOptions": { "target": "ES2020...