← Назад к вопросам
На каком протоколе основан HTTP-запрос
1.3 Junior🔥 151 комментариев
#API и сетевые протоколы
Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI29 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
На каком протоколе основан HTTP-запрос
HTTP (HyperText Transfer Protocol) основан на TCP (Transmission Control Protocol) — это фундаментальное отношение в сетевой архитектуре. Объясню иерархию протоколов и как они работают вместе.
Иерархия сетевых протоколов (OSI модель)
┌────────────────────────────────────────────┐
│ Application Layer (Уровень приложения) │
│ │
│ HTTP, HTTPS, FTP, SMTP, DNS, SSH, WebSocket│
└──────────────────┬─────────────────────────┘
↓
┌────────────────────────────────────────────┐
│ Transport Layer (Транспортный уровень) │
│ │
│ TCP, UDP, SCTP │
└──────────────────┬─────────────────────────┘
↓
┌────────────────────────────────────────────┐
│ Internet Layer (Интернет уровень) │
│ │
│ IP (IPv4, IPv6), ICMP │
└──────────────────┬─────────────────────────┘
↓
┌────────────────────────────────────────────┐
│ Link Layer (Канальный уровень) │
│ │
│ Ethernet, WiFi, PPP │
└────────────────────────────────────────────┘
HTTP и TCP отношение
HTTP использует TCP
const http = require('http');
const server = http.createServer((req, res) => {
res.writeHead(200, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({ message: 'Hello' }));
});
server.listen(3000);
// HTTP сервер слушает на TCP порте 3000
// Каждый HTTP запрос = отдельное TCP соединение
Процесс HTTP запроса
1. CLIENT SERVER
↓ ↓
Устанавливает TCP соединение
(3-way handshake)
────────SYN──────────────→
←─────SYN-ACK─────────────
────────ACK──────────────→
↓ ↓
Отправляет HTTP запрос
────────────────────────────────→
GET /api/users HTTP/1.1
Host: example.com
↓ ↓
Получает HTTP ответ
←────────────────────────────────
HTTP/1.1 200 OK
Content-Length: 42
{"users": []}
↓ ↓
Закрывает TCP соединение
────────FIN──────────────→
←─────ACK─────────────
TCP vs UDP
TCP (Transmission Control Protocol)
Используется HTTP, HTTPS, FTP, SMTP, SSH
const net = require('net');
// TCP сокет (надежный)
const socket = net.createConnection({
host: 'example.com',
port: 80
});
socket.on('connect', () => {
// TCP гарантирует подключение
socket.write('GET / HTTP/1.1\r\nHost: example.com\r\n\r\n');
});
socket.on('data', (chunk) => {
console.log(chunk.toString());
});
Характеристики TCP:
- ✅ Надежность — гарантирует доставку
- ✅ Упорядоченность — данные приходят в правильном порядке
- ✅ Контроль потока — не переполняет получателя
- ✅ Контроль ошибок — обнаруживает и исправляет ошибки
- ❌ Медленнее — требует подтверждений
- ❌ Overhead — больше заголовков
UDP (User Datagram Protocol)
Используется DNS, DHCP, NTP, VoIP, Gaming
const dgram = require('dgram');
// UDP сокет (быстрый)
const client = dgram.createSocket('udp4');
const message = Buffer.from('Hello');
client.send(message, 0, message.length, 53, '8.8.8.8', (err) => {
if (err) {
// UDP не гарантирует доставку!
console.error('Сообщение может быть потеряно');
}
});
client.close();
Характеристики UDP:
- ✅ Скорость — нет overhead'а
- ✅ Простота — просто отправляй
- ✅ Низкая задержка — нет подтверждений
- ❌ Ненадежность — может потеряться
- ❌ Неупорядоченность — может прийти в другом порядке
- ❌ Нет контроля потока
HTTP версии и протоколы
HTTP/1.1 (1997) — TCP
Соединение: одно соединение на один запрос
HTTP/1.1 улучшил: Keep-Alive (переиспользование соединения)
Клиент Сервер
GET /users ─────────────────→
←─────────── 200 OK (users data)
GET /posts ─────────────────→ (переиспользуем TCP соединение!)
←─────────── 200 OK (posts data)
HTTP/2 (2015) — TCP
Мультиплексирование: много запросов в одном TCP соединении
Клиент Сервер
GET /users ─────┐
GET /posts ─────├───────→ (все в одном соединении)
GET /comments ───┘
←─────┬──────────── 200 OK (users)
←─────┼──────────── 200 OK (posts)
←─────┴──────────── 200 OK (comments)
HTTP/3 (2022) — QUIC (based on UDP)
QUIC: более быстрый протокол на основе UDP
Преимущества:
- Faster connection setup (0-RTT)
- Better performance over lossy networks
- Connection migration (смена IP без потери соединения)
HTTPS vs HTTP
HTTP (незащищенный)
const http = require('http');
// Сообщение видно всем в сети
const server = http.createServer((req, res) => {
res.end(JSON.stringify({ token: 'secret123' }));
});
server.listen(80);
// ⚠️ Любой может перехватить: `echo "GET / HTTP/1.1" | nc example.com 80`
HTTPS (защищенный)
const https = require('https');
const fs = require('fs');
const options = {
key: fs.readFileSync('private-key.pem'),
cert: fs.readFileSync('certificate.pem')
};
const server = https.createServer(options, (req, res) => {
res.end(JSON.stringify({ token: 'secret123' }));
});
server.listen(443);
// ✅ Зашифровано TLS/SSL
// Даже если перехватить, это просто gibberish
Процесс TCP соединения (3-way handshake)
Установка соединения
Клиент Сервер
│ │
├─────────────SYN─────────────────────→│
│ (Привет, я готов к соединению) │
│ seq=100 │
│ │
│←────────────SYN-ACK──────────────────┤
│ (OK, я тоже готов) │
│ ack=101, seq=300 │
│ │
├─────────────ACK─────────────────────→│
│ (Подтверждаю) │
│ ack=301 │
│ │
└────── TCP соединение установлено ───┘
TCP в Node.js
HTTP запрос под капотом
const http = require('http');
const options = {
hostname: 'example.com',
port: 80,
path: '/api/users',
method: 'GET'
};
const req = http.request(options, (res) => {
console.log(`STATUS: ${res.statusCode}`);
res.on('data', (chunk) => {
console.log(`BODY: ${chunk}`);
});
res.on('end', () => {
console.log('No more data in response.');
});
});
req.on('error', (e) => {
console.error(`Problem with request: ${e.message}`);
});
req.end();
// На самом деле:
// 1. Создает TCP socket
// 2. Отправляет:
// GET /api/users HTTP/1.1\r\n
// Host: example.com\r\n
// \r\n
// 3. Получает ответ
// 4. Закрывает TCP соединение (или Keep-Alive)
Порты
// HTTP использует TCP порты
const http = require('http');
const server = http.createServer((req, res) => {
res.end('OK');
});
server.listen(3000); // TCP порт 3000
// http://localhost:3000 (используется TCP)
server.listen(80); // TCP порт 80
// http://example.com (стандартный HTTP порт)
server.listen(443); // TCP порт 443
// https://example.com (стандартный HTTPS порт)
Keep-Alive (переиспользование TCP соединения)
HTTP/1.0 (без Keep-Alive)
// Каждый запрос = новое TCP соединение
GET /users HTTP/1.0
Host: example.com
Connection: close // Закрыть соединение после ответа
─── TCP закрывается ───
GET /posts HTTP/1.0
Host: example.com
Connection: close
─── TCP закрывается ───
// 3 запроса = 3 TCP соединения = медленнее
HTTP/1.1 (с Keep-Alive по умолчанию)
// Все запросы в одном TCP соединении
GET /users HTTP/1.1
Host: example.com
Connection: keep-alive
──────────── TCP соединение остается ────────────
GET /posts HTTP/1.1
Host: example.com
Connection: keep-alive
──────────── TCP соединение остается ────────────
GET /comments HTTP/1.1
Host: example.com
Connection: close // Закрыть после этого
─── TCP закрывается ───
// 3 запроса = 1 TCP соединение = быстрее!
Почему HTTP основан на TCP
// Причины:
1. Надежность
- HTTP требует, чтобы данные дошли полностью
- TCP гарантирует это
2. Упорядоченность
- Браузер ожидает ответ в правильном порядке
- TCP гарантирует это
3. Контроль потока
- Сервер может отправлять много данных
- TCP убедится, что клиент все получит
4. Проверка ошибок
- Сеть может быть ненадежной
- TCP обнаружит потерянные пакеты
Альтернативы (почему не UDP)
// Можно ли HTTP на UDP?
// ❌ Нельзя: HTTP требует надежности
const message = Buffer.from('GET / HTTP/1.1\r\nHost: example.com\r\n\r\n');
client.send(message, 0, message.length, 80, 'example.com', (err) => {
// Сообщение может быть потеряно!
// Не узнаем, дошло ли оно
});
// ✅ Можно: QUIC (HTTP/3) на базе UDP
// Но QUIC реализует свой "reliable" layer сверху UDP
Практический пример: Отследить TCP соединение
# Посмотреть TCP соединения
netstat -an | grep ESTABLISHED
# Или с tcpdump
sudo tcpdump -i lo port 3000
# Вывод:
# 10:30:45.123456 IP 127.0.0.1.54321 > 127.0.0.1.3000: Flags [S], seq 1234567
# 10:30:45.123457 IP 127.0.0.1.3000 > 127.0.0.1.54321: Flags [S.], ack 1234568
# 10:30:45.123458 IP 127.0.0.1.54321 > 127.0.0.1.3000: Flags [.], ack 7654321
# ────────────── TCP handshake complete ──────────────
# 10:30:45.123459 IP 127.0.0.1.54321 > 127.0.0.1.3000: Flags [P.], "GET / HTTP/1.1"
# 10:30:45.123460 IP 127.0.0.1.3000 > 127.0.0.1.54321: Flags [P.], "HTTP/1.1 200 OK"
Итоги
HTTP основан на TCP потому что:
- TCP обеспечивает надежность доставки
- TCP обеспечивает упорядоченность данных
- TCP управляет потоком данных
- TCP обнаруживает ошибки
Иерархия:
Application: HTTP/HTTPS (то, что видит разработчик)
Transport: TCP (как данные доставляются)
Internet: IP (как маршрутизируются)
Link: Ethernet (физические провода)
HTTP/3 (QUIC) меняет это:
- Использует UDP вместо TCP
- Но реализует свой "reliable" слой
- Предоставляет лучшую производительность