Работа с сокетами: TCP/UDP клиенты и серверы на Python

🌐 Введение в мир сокетов

Сокеты — это "телефонные розетки" интернета. Они позволяют программам общаться друг с другом через сеть, будь то локальная сеть или весь интернет. В Python работа с сокетами реализована через модуль socket — мощный, но при этом удивительно простой инструмент.

Основные типы сокетов:

  • TCP (SOCK_STREAM) — надежный, с установкой соединения
  • UDP (SOCK_DGRAM) — быстрый, без установки соединения
import socket

# Создаем TCP-сокет
tcp_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

# Создаем UDP-сокет
udp_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

🔌 TCP-сервер: принимаем соединения

TCP-сервер — это "слушатель", который ждет подключений клиентов. Вот как создать простой эхо-сервер:

import socket

def start_tcp_server():
    server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    server_socket.bind(('localhost', 12345))  # Привязываем к адресу и порту
    server_socket.listen(1)  # Начинаем слушать (1 - макс. очередь подключений)

    print("Сервер запущен и ожидает подключений...")

    while True:
        client_socket, addr = server_socket.accept()  # Принимаем подключение
        print(f"Подключен клиент: {addr}")

        data = client_socket.recv(1024)  # Получаем данные (макс. 1024 байт)
        print(f"Получено: {data.decode()}")

        client_socket.sendall(data)  # Отправляем данные обратно
        client_socket.close()  # Закрываем соединение

start_tcp_server()

🔹 Как это работает:

  1. bind() — привязываем сокет к конкретному адресу и порту
  2. listen() — начинаем слушать входящие соединения
  3. accept() — принимаем подключение (блокирующая операция)
  4. recv()/sendall() — получаем и отправляем данные

📱 TCP-клиент: подключаемся к серверу

Теперь создадим клиент, который будет общаться с нашим сервером:

import socket

def start_tcp_client():
    client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    client_socket.connect(('localhost', 12345))  # Подключаемся к серверу

    message = "Привет, сервер!".encode()  # Преобразуем строку в байты
    client_socket.sendall(message)  # Отправляем сообщение

    response = client_socket.recv(1024)  # Получаем ответ
    print(f"Ответ сервера: {response.decode()}")

    client_socket.close()  # Закрываем соединение

start_tcp_client()

🔹 Важные моменты:

  • Все данные передаются в виде байтов (используем encode()/decode())
  • connect() устанавливает соединение с сервером
  • Порядок вызовов должен соответствовать серверу (сначала отправка, потом прием)

🚀 UDP-сервер и клиент: быстрая связь без соединения

UDP работает без установки соединения — просто отправляем пакеты в сеть. Вот пример:

UDP-сервер:

def start_udp_server():
    sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    sock.bind(('localhost', 12345))

    print("UDP-сервер запущен...")

    while True:
        data, addr = sock.recvfrom(1024)  # Получаем данные и адрес отправителя
        print(f"Получено от {addr}: {data.decode()}")
        sock.sendto(data, addr)  # Отправляем ответ обратно

start_udp_server()

UDP-клиент:

def start_udp_client():
    sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

    message = "Привет, UDP-сервер!".encode()
    sock.sendto(message, ('localhost', 12345))  # Отправляем сообщение

    response, _ = sock.recvfrom(1024)  # Получаем ответ
    print(f"Ответ сервера: {response.decode()}")

    sock.close()

start_udp_client()

🔹 Ключевые отличия UDP:

  • Нет connect()/accept() — соединение не устанавливается
  • Используем sendto() и recvfrom() вместо send()/`recv()
  • Меньше накладных расходов, но нет гарантии доставки

🛠️ Продвинутые техники

Неблокирующие сокеты

server_socket.setblocking(False)  # Делаем сокет неблокирующим

Таймауты

client_socket.settimeout(5.0)  # Устанавливаем таймаут 5 секунд

Мультиплексирование с select

import select

readable, _, _ = select.select([server_socket], [], [], 5.0)
if server_socket in readable:
    client_sock, addr = server_socket.accept()

Для более сложных сценариев стоит изучить модули asyncio или multiprocessing.


🎯 Практическое применение

Сокеты используются везде:

  • Веб-серверы (HTTP — это поверх TCP)
  • Онлайн-игры (часто используют UDP)
  • Чат-приложения
  • IoT-устройства

Попробуйте улучшить наш пример:

  1. Добавьте обработку нескольких клиентов одновременно (потоки или асинхронность)
  2. Реализуйте простой протокол (например, команды для сервера)
  3. Сделайте кроссплатформенный чат

Для глубокого погружения в сетевые технологии Python рекомендую курсы Данилы Бежина на YouTube: https://www.youtube.com/@DanilaBezhin. Там вы найдете разборы реальных кейсов и продвинутые техники работы с сетью.

Скрыть рекламу навсегда

🌱 Индвидидулаьные занятия

Индивидуальные онлайн-занятия по программированию для детей и подростков

Личный подход, без воды, с фокусом на понимание и реальные проекты.

🚀 Записаться на занятие