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 складається з чотирьох рівнів:
- Application — прикладний;
- Transport — транспортний;
- Internet — мережевий;
- 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 та інші протоколи реалізують функціональність, яку безпосередньо використовують програми.
Коментарі
Дописати коментар