Python-сокеты и UDP: как очередь пакетов помогает отправителю быстрее, чем получателю - PullRequest
0 голосов
/ 06 ноября 2019

Есть получатель, который зацикливается и вызывает socket.recv:

import socket
import time

UDP_IP = "127.0.0.1"
UDP_PORT = 5005

sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)  # Internet  # UDP

sock.bind((UDP_IP, UDP_PORT))

sock.settimeout(0.001)

while True:
    try:
        data = sock.recv(1024)  # buffer size is 1024 bytes
    except socket.timeout:
        pass

    time.sleep(0.01)

А отправитель зацикливается и отправляет сообщения с socket.sendto, считая вверх:

import socket

UDP_IP = "127.0.0.1"
UDP_PORT = 5005

sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)  # Internet  # UDP

TOTAL_TO_SEND = 10000

messages = [str.encode(f"{num}") for num in range(TOTAL_TO_SEND)]

for total_sent in messages:
    sock.sendto(total_sent, (UDP_IP, UDP_PORT))

При такой настройке приемник не достаточно быстро зацикливается, чтобы вернуться к строке recv к тому времени, когда отправитель отправил следующее сообщение.

Поскольку UDP разрешает потерянные данные, я подумал, что, возможно,Сообщения, поступившие, пока получатель еще не вернулся к recv, будут просто пропущены. Но это не так.

Когда я отправляю только 10 000 сообщений (TOTAL_TO_SEND = 10000), даже если отправка заканчивается почти мгновенно, получателю требуется некоторое время, чтобы пройти через все 10000 сообщений, но он не пропускаетЛюбые. Это подразумевает наличие некоторого буфера / очереди для сообщений, поступивших, пока получатель не был готов, и они хранятся до тех пор, пока код получателя не сможет обработать их все.

Но когда я отправляю в 10 раз большесообщения (TOTAL_TO_SEND = 100000), есть некоторая отсечка (15355 для моего последнего запуска), ниже которой обрабатывается каждое отдельное сообщение, после чего оно пропускается сотнями за раз. Для меня это означает, что буфер / очередь заполнились, и тогда цикл был достаточно быстрым, чтобы обрабатывать одно сообщение из каждой отправленной пары сотен.

Еще одним свидетельством теории конечных размеров очереди является то, что увеличениеразмер сообщения (добавляя около 0 к каждому сообщению) уменьшает отсечку, когда сообщения начинают пропускаться. Добавление 100 0 к каждому сообщению приводит к тому, что отсечение становится равным 641 вместо 15355.

Мне не удалось найти подробное объяснение этого поведения, поэтому я удивлялся, знает ли кто-нибудь здесь, как работает эта «очередь пакетов»в сокетах Python, и каковы его параметры. Известен ли его размер? Можно ли его увеличить? Существует ли ограничение по времени до исчезновения сообщений? Есть ли документация по этому поводу?

Спасибо!

1 Ответ

0 голосов
/ 06 ноября 2019

Это не совсем «подробное объяснение», но некоторая информация:

Вы можете просматривать и устанавливать параметры для сокета в Python с помощью getsockopt и setsockopt .

Соответствующим параметром в этом случае является размер буфера приема, т.е. socket.SO_RCVBUF.

print(sock.getsockopt(socket.SOL_SOCKET, socket.SO_RCVBUF))

показал мне 65536.

Вы можетеиспользуйте

sock.setsockopt(socket.SOL_SOCKET, socket.SO_RCVBUF, 65536 * 100)

, чтобы увеличить его в 100 раз. Это приводит к тому, что в буфере сохраняется в 100 раз больше данных, прежде чем сообщения начинают пропускаться.

Создание слишком большого размера может быть плохой идеей, но я не знаю, поэтому я позволю кому-то другомувмешайтесь в это.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...