Страницы

Поиск по вопросам

воскресенье, 8 марта 2020 г.

Сокеты в python: параметр backlog у socket.listen() метода

#python_3x #сокет


Здравствуйте. Написал простое клиент-серверное приложение используя сокеты. Клиент
отправляет строку серверу, сервер переводит эту строку в верхний регистр и отправляет
клиенту, а клиент просто печатает эту строку.

#Сервер
import socket
from threading import Thread

def handler(client_socket, cli_address):
    print(client_address, 'was connected')
    while 1:
        recieve_message = client_socket.recv(1024)
        client_socket.send(recieve_message.upper())

server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_socket.bind(('127.0.0.1', 5000))
print('server starts')
server_socket.listen(1)
while 1:
    client_socket, client_address = server_socket.accept()
    Thread(target=handler, args=(client_socket, client_address)).start()
#-----------------------------------------
#Клиент
import socket

client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client_socket.connect(('127.0.0.1', 5000))
while 1:
    message = input()
    client_socket.send(message.encode())
    recieve_message = client_socket.recv(1024)
    print(recieve_message.decode())


Вопрос вызывает метод listen. В качестве параметра он принимает максимальное число
соединений. В данном случает он равняется 1. Но запустив сервер и пять клиентов, все
они благополучно работают, почему?
    


Ответы

Ответ 1



Вы не совсем правильно понимаете этот параметр у listen. Как происходит работа серверного сокета: клиент подключается к серверу. его ставят в очередь (и этот параметр у listen определяет размер очереди) если в очереди уже нет места - клиенту отказывают в подключении. отдельно сам сервер вызывает accept для сокета. Этим он забирает одного клиента с очереди сокетов, ожидающих подключение. Теперь законный вопрос, а сколько же ставить размер очереди? Она должна быть такой, что бы код успевал принять всех клиентов. То есть, если Вы тестируете и подкючаетесь одним клиентом и следующее подключение будет только после обрабоки предыдущего, то даже размер в 1 будет достаточный. Если же у Вас тяжело нагруженный сервер и клиенты туда валят сотнями, а в коде могут быть затыки по accept'у клиентов, то нужно ставить побольше, я видел и 100, и 150. Но если клиенты валят с такой скоростью, что код не успевает их выгребать, то тут никакой размер очереди не поможет.

Ответ 2



Из документации для socket.listen([backlog]): Enable a server to accept connections. If backlog is specified, it must be at least 0 (if it is lower, it is set to 0); it specifies the number of unaccepted connections that the system will allow before refusing new connections. If not specified, a default reasonable value is chosen.(выделение моё) Выделенная часть говорит, что backlog параметр определяет число непринятых соединений, после которых новые соединения отвергаются. Что такое непринятое соединение и/или кол-во очередей связанных с новыми соединениями может зависеть от системы, например, см. man listen(2) и если хочется подробностей: How TCP backlog works in Linux. "Непринятое" соединение—это вероятно соединение, для которого socket.accept() метод не был вызван. Поэтому даже с server_socket.listen(1) ваш сервер может сколько угодно (пока кол-во запущенных потоков систему не подвесит) одновременных клиентов обслуживать, если между открытиями новых соединений достаточна пауза, чтобы новый поток запустился и следующий server_socket.accept() мог бы вернуться.

Комментариев нет:

Отправить комментарий