Listen: примеры (PYTHON)
listen(backlog): NoneОсновы функции listen
Метод listen() в Python применяется для объектов сокетов и переводит их в состояние прослушивания входящих подключений. Он используется при создании сетевых серверов, принимающих TCP-соединения.
Аргументы:
backlog(необязательный) - целое число, определяющее максимальное количество ожидающих подключений в очереди. Если очередь заполнена, новые подключения отклоняются. Значение по умолчанию зависит от операционной системы, обычно это 5.
Метод не возвращает значений. Вызов listen() без предварительного связывания с адресом через bind() приводит к ошибке.
Примеры использования
Простейший сервер с использованием listen:
import socket
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_socket.bind(('localhost', 8888))
server_socket.listen(1)
print("Сервер слушает порт 8888")
client_socket, addr = server_socket.accept()
print(f"Подключение от {addr}")
client_socket.close()
server_socket.close()Сервер слушает порт 8888
Подключение от ('127.0.0.1', 54321)Использование другого значения backlog:
server_socket.listen(10)
print(f"Сервер настроен на очередь из 10 подключений")Сервер настроен на очередь из 10 подключений
Похожие функции в Python
Для создания сетевых серверов в Python существуют альтернативные инструменты.
socketserver- высокоуровневый модуль, упрощающий создание серверов. Подходит для быстрого прототипирования, скрывает детали обработки подключений.asyncio.start_server()- асинхронная функция для создания серверов. Используется в асинхронном коде, эффективно обрабатывает множество одновременных подключений.multiprocessing.Listener- объект для межпроцессного взаимодействия. Создает сервер для обмена данными между процессами, не использует сетевые порты.
Выбор зависит от задач: для простых TCP-серверов подходит socket.listen(), для асинхронных приложений - asyncio, для высокоуровневых решений - socketserver.
Аналоги в других языках
PHP: Функция socket_listen() выполняет ту же роль.
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
socket_bind($socket, '127.0.0.1', 8888);
socket_listen($socket, 5);
echo "Сервер слушает";Сервер слушает
JavaScript (Node.js): Метод server.listen() у объекта net.Server.
const net = require('net');
const server = net.createServer();
server.listen(8888, 'localhost');
console.log("Сервер запущен");Сервер запущен
Java: Метод ServerSocket.listen() отсутствует, прослушивание начинается после создания объекта с указанием порта.
ServerSocket serverSocket = new ServerSocket(8888);
System.out.println("Сервер запущен");Сервер запущен
C#: Метод TcpListener.Start() начинает прослушивание.
TcpListener listener = new TcpListener(IPAddress.Any, 8888);
listener.Start();
Console.WriteLine("Сервер запущен");Сервер запущен
Типичные ошибки
Вызов listen() до метода bind() вызывает ошибку.
import socket
sock = socket.socket()
try:
sock.listen()
except OSError as e:
print(f"Ошибка: {e}")Ошибка: [Errno 22] Invalid argument
Указание отрицательного значения backlog приводит к ошибке в некоторых системах.
server_socket.bind(('localhost', 8888))
try:
server_socket.listen(-1)
except OverflowError as e:
print(f"Ошибка: {e}")Ошибка: can't convert negative int to unsigned
Попытка использования на сокете, уже переведенном в состояние прослушивания.
server_socket.listen()
server_socket.listen() # Повторный вызов# Ошибки не возникает, но это избыточная операция
Изменения в последних версиях
В Python 3.5 появилась поддержка контекстного менеджера для объектов сокетов, что упрощает их закрытие, но не затрагивает непосредственно метод listen().
В Python 3.8 оптимизирована внутренняя реализация сетевого стека, что может влиять на производительность listen() при больших значениях backlog, но синтаксис и поведение остались прежними.
Начиная с Python 3.10, в документации явно указано, что значение backlog может быть установлено в 0 для отключения очереди подключений, хотя такая возможность существовала и ранее.
Расширенные примеры
Сервер с обработкой нескольких клиентов в цикле:
import socket
server = socket.socket()
server.bind(('', 9090))
server.listen(3)
print("Сервер запущен")
while True:
client, addr = server.accept()
data = client.recv(1024)
print(f"От {addr}: {data.decode()}")
client.send(b"Hello from server")
client.close()Сервер запущен
От ('127.0.0.1', 54321): Привет
От ('127.0.0.1', 54322): ТестИспользование backlog равным 0, что отключает очередь подключений:
server_socket.listen(0)
print("Очередь подключений отключена, новые соединения будут немедленно отклоняться, если сервер занят")Очередь подключений отключена, новые соединения будут немедленно отклоняться, если сервер занят
Создание сервера с возможностью повторного использования адреса:
server = socket.socket()
server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
server.bind(('localhost', 8888))
server.listen()
print("Сервер с возможностью повторного использования адреса")Сервер с возможностью повторного использования адреса
Измерение времени между вызовом listen и первым accept:
import time
server.listen(5)
start = time.time()
client, addr = server.accept()
elapsed = time.time() - start
print(f"Первый клиент подключился через {elapsed:.2f} секунд")Первый клиент подключился через 1.53 секунд