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

В чём разница между TCP и UDP?

1.8 Middle🔥 191 комментариев
#REST API и HTTP

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Разница между TCP и UDP: Полный разбор

ТCP и UDP — это два основных протокола транспортного слоя (Layer 4) в сетевой модели OSI. Несмотря на то, что оба работают на одном уровне, они имеют принципиально разные подходы к передаче данных.

TCP (Transmission Control Protocol)

TCP — это надёжный, ориентированный на соединение протокол. Гарантирует доставку всех пакетов в правильном порядке.

Характеристики TCP:

  • Соединение: требует установление соединения (3-way handshake)
  • Надёжность: гарантирует доставку всех пакетов
  • Порядок: пакеты приходят в правильном порядке
  • Контроль потока: проверяет скорость отправки
  • Контроль перегрузки: адаптируется к нагрузке сети
  • Обнаружение ошибок: проверяет целостность данных
  • Медлительность: больше накладных расходов
  • Надёжное соединение: требует больше ресурсов
import socket

# TCP СЕРВЕР
def tcp_server():
    server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    server_socket.bind(('localhost', 5000))
    server_socket.listen(1)
    print("TCP Сервер слушает на порту 5000...")
    
    connection, client_address = server_socket.accept()
    try:
        print(f"Подключен: {client_address}")
        data = connection.recv(1024)
        print(f"Получено: {data.decode()}")
        connection.send(b"Ответ получен")
    finally:
        connection.close()
        server_socket.close()

# TCP КЛИЕНТ
def tcp_client():
    client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    client_socket.connect(('localhost', 5000))
    client_socket.send(b"Hello, TCP!")
    response = client_socket.recv(1024)
    print(f"Ответ сервера: {response.decode()}")
    client_socket.close()

UDP (User Datagram Protocol)

UDP — это простой, без соединения протокол. Не гарантирует доставку, но намного быстрее.

Характеристики UDP:

  • Без соединения: отправляет сразу, без подготовки
  • Ненадёжность: может потерять пакеты
  • Беспорядок: пакеты могут прийти не в порядке
  • Без контроля потока: отправляет столько, сколько нужно
  • Без контроля перегрузки: не адаптируется
  • Минимальная проверка: только базовая проверка целостности
  • Быстрота: минимальные накладные расходы
  • Дешевизна: использует меньше ресурсов
import socket

# UDP СЕРВЕР
def udp_server():
    server_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    server_socket.bind(('localhost', 5001))
    print("UDP Сервер слушает на порту 5001...")
    
    data, client_address = server_socket.recvfrom(1024)
    print(f"Получено от {client_address}: {data.decode()}")
    server_socket.sendto(b"Ответ получен", client_address)
    server_socket.close()

# UDP КЛИЕНТ
def udp_client():
    client_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    client_socket.sendto(b"Hello, UDP!", ('localhost', 5001))
    response, _ = client_socket.recvfrom(1024)
    print(f"Ответ сервера: {response.decode()}")
    client_socket.close()

Таблица различий

ПараметрTCPUDP
ТипОриентирован на соединениеБез соединения
Установка соединенияТребуется (3-way handshake)Не требуется
Надёжность доставкиГарантирует доставкуНет гарантии
Порядок пакетовПравильный порядокМожет быть беспорядок
СкоростьМедленнее (много проверок)Быстрее (мало проверок)
Контроль потокаДаНет
Контроль перегрузкиДаНет
Накладные расходыБольшиеМинимальные
Размер заголовка20 байт8 байт
Повторная передачаАвтоматическаяНет
Использование памятиМного (буферы соединения)Мало
ПримерыHTTP/HTTPS, Email, FTPDNS, Online игры, VoIP, Streaming

Сравнение установки соединения

TCP: 3-Way Handshake

Клиент                    Сервер
  |                         |
  |-------- SYN -------->    |  (1) Клиент инициирует
  |                         |
  |     <------ SYN-ACK      |  (2) Сервер отвечает
  |<----- (подтверждение)   |
  |                         |
  |-------- ACK -------->    |  (3) Клиент подтверждает
  |                         |
  | [Соединение установлено] |
  |<--------- DATA -------->  |
  |                         |

UDP: Прямая отправка

Клиент                    Сервер
  |                         |
  |--------- DATA -------->  |  Готово!
  |                         |

Практические примеры

Пример 1: Веб-приложение (TCP)

# HTTP/HTTPS использует TCP
import socket

def fetch_website():
    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    sock.connect(('example.com', 80))
    
    request = b"GET / HTTP/1.1\r\nHost: example.com\r\n\r\n"
    sock.send(request)
    
    response = b""
    while True:
        chunk = sock.recv(4096)
        if not chunk:
            break
        response += chunk
    
    sock.close()
    return response

# TCP гарантирует, что весь HTTP ответ доставлен полностью

Пример 2: DNS запрос (UDP)

# DNS использует UDP
import socket

def dns_query(domain):
    sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    
    # Отправка DNS запроса
    dns_server = '8.8.8.8'  # Google DNS
    dns_port = 53
    
    # Простой DNS пакет (не реальный, для примера)
    query = b'\x12\x34\x01\x00\x00\x01\x00\x00\x00\x00\x00\x00'
    sock.sendto(query, (dns_server, dns_port))
    
    # UDP может потерять запрос, но для DNS это нормально
    # Есть timeout и переотправка на уровне приложения
    response, _ = sock.recvfrom(512)
    sock.close()
    return response

# UDP быстрый, потеря редкая

Пример 3: Онлайн игра (UDP)

import socket
import time

class GameClient:
    def __init__(self, server_host, server_port):
        self.socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        self.server_address = (server_host, server_port)
    
    def send_position(self, x, y, z):
        """Отправить позицию игрока"""
        message = f"POS:{x},{y},{z}".encode()
        self.socket.sendto(message, self.server_address)
        # UDP не гарантирует доставку
        # Но отправляем позицию часто (30-60 раз в сек)
        # Если одно сообщение потеряется — не страшно
    
    def receive_updates(self):
        """Получить обновления от сервера"""
        data, _ = self.socket.recvfrom(1024)
        return data.decode()

# UDP идеален для игр: быстрый, потери незаметны

Пример 4: VoIP (UDP)

import socket
from datetime import datetime

class VoIPClient:
    def __init__(self, server_host, server_port):
        self.socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        self.server_address = (server_host, server_port)
    
    def send_audio_packet(self, audio_data):
        """Отправить audio пакет"""
        packet = b"AUDIO:" + audio_data
        self.socket.sendto(packet, self.server_address)
        # VoIP использует UDP:
        # - Нужна минимальная задержка
        # - Потеря одного пакета незаметна
        # - Быстрота важнее надёжности

# UDP: низкая задержка, высокая пропускная способность

Когда использовать TCP

# ✓ ИСПОЛЬЗУЙТЕ TCP ДЛЯ:
applications = {
    'HTTP/HTTPS': 'Веб-приложения, REST API',
    'Email': 'SMTP, POP3, IMAP',
    'File Transfer': 'FTP, SFTP',
    'SSH': 'Удалённый доступ',
    'Database': 'MySQL, PostgreSQL',
    'Messaging': 'Telegram, WhatsApp',
    'Banking': 'Финансовые приложения',
}

ТCP гарантирует доставку каждого бита данных. Критично для:

  • Финансовых транзакций
  • Работы с файлами
  • Долгих соединений
  • Когда потеря данных неприемлема

Когда использовать UDP

# ✓ ИСПОЛЬЗУЙТЕ UDP ДЛЯ:
applications = {
    'DNS': 'Разрешение имён',
    'Online Gaming': 'Multiplayer игры',
    'Video Streaming': 'YouTube, Netflix',
    'VoIP': 'Skype, Zoom',
    'Live Events': 'Live трансляции',
    'IoT': 'Интернет вещей датчики',
    'DHCP': 'Выдача IP адресов',
}

UDP используется когда:

  • Скорость критичнее надёжности
  • Потеря пакета допустима
  • Нужна минимальная задержка (low latency)
  • Высокий объём данных

Гибридный подход

# QUIC протокол (UDP-based, но с гарантиями TCP)
import socket

# QUIC = UDP + надёжность TCP
# Новый стандарт для HTTP/3
# Используется в Chrome, Firefox и др.

def quic_connection():
    # В будущем QUIC заменит много TCP приложений
    sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    # QUIC добавляет надёжность поверх UDP
    # Лучшее из обоих миров!
    pass

Практическое сравнение производительности

import socket
import time

def test_tcp():
    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    start = time.time()
    sock.connect(('example.com', 80))
    elapsed = time.time() - start
    print(f"TCP подключение: {elapsed*1000:.1f}ms")
    sock.close()

def test_udp():
    sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    start = time.time()
    sock.sendto(b"test", ('example.com', 53))
    elapsed = time.time() - start
    print(f"UDP отправка: {elapsed*1000:.3f}ms")
    sock.close()

# UDP обычно быстрее на порядок!

Заключение

TCP: надёжный, медленный, гарантирует доставку. Для приложений где потеря данных критична (веб, email, банк).

UDP: быстрый, ненадёжный, без гарантий. Для приложений где скорость критична (игры, потоковое видео, VoIP).

Правило: Сомневаетесь — выбирайте TCP. Если нужна скорость больше, чем надёжность — UDP.

В чём разница между TCP и UDP? | PrepBro