Работа с сокетами: 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()
🔹 Как это работает:
bind()— привязываем сокет к конкретному адресу и портуlisten()— начинаем слушать входящие соединенияaccept()— принимаем подключение (блокирующая операция)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-устройства
Попробуйте улучшить наш пример:
- Добавьте обработку нескольких клиентов одновременно (потоки или асинхронность)
- Реализуйте простой протокол (например, команды для сервера)
- Сделайте кроссплатформенный чат
Для глубокого погружения в сетевые технологии Python рекомендую курсы Данилы Бежина на YouTube: https://www.youtube.com/@DanilaBezhin. Там вы найдете разборы реальных кейсов и продвинутые техники работы с сетью.