Может ли быть установлено минимальное количество байтов для сокета python.recvfrom()?

#python #python-3.x #sockets #udp #packet

Вопрос:

Есть 2 типа пакетов, которые я отправляю с моего сервера и пытаюсь проанализировать:

  • контекстные пакеты длиной 27 слов (108 байт)
  • пакеты данных длиной 250 слов (1000 байт)

Я использую метод сокета python recvfrom (), но документации об этом, похоже, недостаточно.. В настоящее время у меня есть следующий фрагмент кода:

 import socket   rx_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) rx_socket.bind(("", 50000))  packets = [] for _ in range(10):  data, _ = rx_socket.recvfrom(8192)  packets.append(data)  

Моя проблема в том, что для каждого пакета, который попадает в packets список, это контекстный пакет. Я знаю это, потому что длина каждого элемента равна 27. Мне нужно иметь возможность получать пакеты данных, есть ли способ указать минимальное количество байтов до возврата recvfrom ()? Спасибо вам за любую помощь!

Ответ №1:

есть ли способ указать минимальное количество байтов перед возвратом функции recvfrom ()?

Нет. Можно указать только максимальное количество байтов для чтения.

Обратите внимание, однако, что с помощью дейтаграмм (т. е. UDP) каждый recv вернет ровно одну датаграмму и send отправит все, что указано в одной датаграмме, что также означает, что между send одной и другой сторонами существует соотношение 1:1 recv .

Также невозможно выбрать дейтаграммы на основе их размера и позволить системе игнорировать другие. Все доставляется в буфер сокета (до тех пор, пока есть место) в полученном заказе. Единственный способ добраться до больших дейтаграмм — это явно удалить все полученные ранее дейтаграммы, позвонив recv .

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

1. Значит ли это, что каждый вызов recv() будет возвращать один пакет независимо от размера буфера? Может быть, добавление a while True и проверка до тех пор, пока длина не превысит 27, помогут?

2. @Tonysres: да, каждый вызов recv would возвращает следующую дейтаграмму. Если заданная длина меньше длины дейтаграммы, то остальные данные будут отброшены, т. е. не будут возвращены в следующем recv . Таким образом, выполнение цикла recv и пропуск всех дейтаграмм с 27 словами будут работать.

Ответ №2:

Моя проблема в том, что для каждого пакета, который попадает в packets список, это контекстный пакет. Я знаю это, потому что длина каждого элемента равна 27.

Ну, вы читаете только 10 пакетов, а затем останавливаетесь. Возможно ли, что data пакеты поступают после пакета 10?

Мне нужно иметь возможность получать data пакеты

recvfrom() Звонок, который у вас уже есть, прекрасно подойдет для этой цели. Вы говорите recvfrom() , чтобы прочитать следующую дейтаграмму, используя буфер 8K. Ваши data пакеты находятся в пределах этого размера.

Во всяком случае, единственное, что вам нужно изменить, — это состояние цикла, например, используя while True вместо for _ in range(10) .

Если вы не получаете никаких data пакетов, это означает, что либо вы прекращаете чтение до их поступления, либо они просто не отправляются на ваш порт прослушивания с самого начала. Используйте анализатор пакетов, например Wireshark, чтобы убедиться в этом.

есть ли способ указать минимальное количество байтов перед возвратом функции recvfrom ()?

Нет, это не так. Каждый вызов recvfrom() будет отменять очередь и возвращать следующую дейтаграмму в сокете, независимо от его размера. Однако, если размер дейтаграммы превышает указанный вами размер буфера, дейтаграмма будет усечена.