← Назад к вопросам

На каком протоколе основан 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" слой
  • Предоставляет лучшую производительность
На каком протоколе основан HTTP-запрос | PrepBro