Сокет — это конечная точка сетевого соединения, заданная парой из IP-адреса и номера порта, через которую программа отправляет и принимает данные. Проще говоря, сокет — это «розетка», в которую приложение включается, чтобы обмениваться данными по сети с другой программой.
Содержание
Ниже разберем, из чего состоит сокет и на каком уровне он работает, чем отличаются сокеты TCP и UDP, как устроена клиент-серверная модель и какие шаги проходит соединение. В конце — рабочий пример клиент-сервера на Python с фактическим выводом и разбор частых ошибок.
Что такое сокет и как он работает
Сокет однозначно определяется парой значений: IP-адрес и номер порта. IP-адрес указывает на конкретное устройство в сети, а порт — на конкретную программу или службу на этом устройстве. Например, веб-сервер обычно слушает порт 443 (HTTPS), а почтовый сервер — порт 25.
Полное соединение описывается уже четверкой: IP и порт клиента плюс IP и порт сервера. Именно поэтому к одному порту сервера могут быть одновременно подключены сотни клиентов — их различают по адресу и порту на стороне клиента.
Сам сокет создает и обслуживает операционная система. Для программы он выглядит как объект (в Unix — как файловый дескриптор), в который можно писать данные и из которого можно читать. Реальную доставку байтов по сети берет на себя сетевой стек ОС, а приложение работает с удобным интерфейсом.
Виды сокетов: TCP и UDP
Чаще всего под сокетами понимают два типа — потоковые (TCP) и датаграммные (UDP). Выбор между ними определяется тем, что важнее: надежность доставки или скорость и минимальные задержки.
| Признак | TCP (потоковый, SOCK_STREAM) | UDP (датаграммный, SOCK_DGRAM) |
|---|---|---|
| Соединение | С установкой соединения | Без установки соединения |
| Гарантия доставки | Есть, с переотправкой потерь | Нет, пакет может потеряться |
| Порядок данных | Сохраняется | Не гарантируется |
| Скорость и накладные расходы | Медленнее, накладных расходов больше | Быстрее, минимум накладных расходов |
| Где применяют | Веб, почта, передача файлов, БД | Онлайн-игры, видеозвонки, DNS, стриминг |
Ориентир для выбора простой. Нужна гарантия, что данные дойдут целиком и по порядку (загрузка страницы, файл, запрос к базе) — берут TCP. Важнее скорость и свежесть данных, а редкая потеря пакета некритична (голос, видео, игровое положение игрока) — берут UDP. В большинстве учебных задач на Python по умолчанию используют TCP.
Клиент-серверная модель и этапы соединения
В клиент-серверной модели одна сторона (сервер) ждет подключений, другая (клиент) их инициирует. Роли задаются набором вызовов сокета.
На стороне сервера порядок такой:
socket()— создать сокет;bind()— привязать сокет к IP и порту;listen()— перевести сокет в режим ожидания входящих подключений;accept()— принять подключение и получить отдельный сокет для общения с этим клиентом.
На стороне клиента шагов меньше: socket() создает сокет, а connect() подключается к адресу и порту сервера. Дальше обе стороны обмениваются данными через send() и recv() и закрывают соединение через close().
Для TCP перед обменом данными происходит «трехэтапное рукопожатие» (three-way handshake): клиент шлет пакет SYN, сервер отвечает SYN-ACK, клиент подтверждает пакетом ACK. Только после этого канал готов. У UDP такого шага нет — данные отправляют сразу.
Сокеты в Python: пример клиент-сервер
В стандартной библиотеке Python за работу с сокетами отвечает встроенный модуль socket — ставить ничего не нужно. Примеры ниже проверены на Python 3.12. Задача: клиент запрашивает у сервера текущие дату и время.
Сначала сервер. Запускать его нужно первым, в отдельном терминале.
import socket
from datetime import datetime
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind(("localhost", 7777)) # привязка к адресу и порту
server.listen(5) # 5 - размер очереди ожидающих подключений
print("Сервер слушает порт 7777, жду клиента...")
conn, addr = server.accept() # блокируется, пока не подключится клиент
print("Клиент подключился:", addr)
now = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
conn.sendall(now.encode("utf-8")) # строку перед отправкой кодируем в байты
conn.close()
server.close()
Вывод в терминале сервера после подключения клиента:
Сервер слушает порт 7777, жду клиента...
Клиент подключился: ('127.0.0.1', 54134)
Теперь клиент — запускаем во втором терминале:
import socket
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect(("localhost", 7777)) # адрес и порт сервера
data = client.recv(1024) # принять до 1024 байт
print("Время от сервера:", data.decode("utf-8")) # байты обратно в строку
client.close()
Вывод в терминале клиента:
Время от сервера: 2026-09-09 14:22:05
Два момента, которые важно понять на этом примере. Число в listen(5) — это длина очереди еще не принятых подключений, а не число «одновременных клиентов»: чтобы обслуживать многих клиентов сразу, accept() вызывают в цикле и обрабатывают каждого в отдельном потоке или через асинхронность. Размер буфера в recv(1024) задает верхнюю границу порции за одно чтение: слишком маленький буфер заставит читать много раз, слишком большой зря займет память, поэтому обычно берут степень двойки от 1024 до 8192 байт.
Частые ошибки
Метод bind, а не blind. Опечатка встречается часто, потому что слова похожи.
server.blind(("localhost", 7777))
Результат:
AttributeError: 'socket' object has no attribute 'blind'
Исправление — правильное имя метода:
server.bind(("localhost", 7777))
Через сокет передают байты, а не строку. Если отправить обычную строку, Python выдаст ошибку типа.
client.send("привет")
Результат:
TypeError: a bytes-like object is required, not 'str'
Исправление — закодировать строку в байты перед отправкой:
client.send("привет".encode("utf-8"))
Клиент стартовал раньше сервера. Если сервер еще не слушает порт, connect() завершится ошибкой.
ConnectionRefusedError: [Errno 61] Connection refused
Исправление — сначала запустить сервер (он должен дойти до listen() и accept()), затем клиента; при разработке подключение можно оборачивать в повтор с паузой.
Выводы
- Сокет — это конечная точка соединения, однозначно заданная парой IP-адрес и порт; создает и обслуживает его операционная система, а программа работает с ним как с объектом для чтения и записи.
- Полное TCP-соединение определяется четверкой адрес-порт клиента и адрес-порт сервера, поэтому один порт сервера обслуживает множество клиентов одновременно.
- TCP дает надежную упорядоченную доставку и подходит для веба, файлов и баз данных; UDP быстрее и без гарантий — для голоса, видео и игр.
- Роли в клиент-серверной модели задаются вызовами: сервер идет по цепочке
socket -> bind -> listen -> accept, клиент —socket -> connect. - В Python сокеты доступны сразу через встроенный модуль
socket; данные передаются в виде байтов, поэтому строки кодируют черезencodeи декодируют черезdecode.
Где применяется / связь с практикой
Сокеты — это фундамент, поверх которого работают привычные вещи: браузер и веб-сервер, мессенджеры, онлайн-игры, обмен данными между сервисами. Понимание сокетов помогает осознанно писать сетевой код, отлаживать зависшие соединения и грамотно выбирать между TCP и UDP.
Освойте тему на практике
Если хочется дойти от синтаксиса Python до уверенной работы с сетью и сокетами на практике, посмотрите программу курса Python Basic — там сетевые задачи разбирают на живых примерах. Оценить формат и уровень до старта помогают открытые уроки: расписание есть на странице бесплатных вебинаров.
Смежные темы: Клиент-серверная модель в Питоне и сокеты, Логирование в Python.
FAQ
Сокет и порт — это одно и то же?
Нет. Порт — это только число, которое указывает на программу на устройстве. Сокет — это конечная точка соединения целиком, то есть пара из IP-адреса и порта плюс объект в операционной системе, через который идет обмен данными.
Сколько клиентов может обслуживать один порт сервера?
Технически много: соединения различаются по четверке адрес-порт клиента и сервера, а не по одному порту. Реальный предел задают ресурсы машины и способ обработки — потоки, процессы или асинхронность.
Нужны ли сторонние библиотеки для сокетов в Python?
Нет, базовой работы хватает встроенного модуля socket. Сторонние инструменты (например, asyncio для асинхронности или фреймворки) берут, когда нужно обслуживать много соединений одновременно или строить высокоуровневый протокол.



