Поиск SSDP в сокетах Python работает непоследовательно в WindowsPython

Программы на Python
Ответить Пред. темаСлед. тема
Anonymous
 Поиск SSDP в сокетах Python работает непоследовательно в Windows

Сообщение Anonymous »

Цель
Я пишу приложение для Windows на Python, которому необходимо искать доступные сетевые устройства с помощью ssdp. Поиск будет использоваться для получения IP-адресов определенных типов устройств для установки соединения.
Проблема
Мы получали очень непоследовательный поиск по ssdp. результаты. Иногда это работает, иногда терпит неудачу. Используя Wireshark и Device Sniffer (из инструментов Meshcommander UPnP), мы обнаружили, что в случае сбоя ssdp M-SEARCH отправляется на адрес 127.0.0.1, поэтому он никогда не достигает сети. Кажется, нет никакой закономерности или причины, когда это работает или терпит неудачу. Я уверен, что это характерно для Windows, поскольку тот же код без проблем работает на Mac.
Код, который работает с перерывами:

Код: Выделить всё

import socket
import struct
import time

local_ip = '192.168.20.48'
ssdp_addr = "239.255.255.250"
ssdp_port = 1900
searchterm = 'ssdp:all'

m_msg = f"""\
M-SEARCH * HTTP/1.1\r\n\
Host: {ssdp_addr}:{ssdp_port}\r\n\
Man: "ssdp:discover"\r\n\
ST: {searchterm}\r\n\
MX: 2\r\n\r\n""".encode("utf-8")

if __name__ == "__main__":
# Method 1, occassionally works. Most of the time sends to 127.0.0.1:port
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sock.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_TTL, 5)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
sock.settimeout(5)
sock.sendto(m_msg, (ssdp_addr, ssdp_port)) # Sometimes works, sometimes doesn't...

# If send worked, this will receive the response. But, if send is routed to 127.0.0.1,
# nothing is received (which is expected given it is localhost)
tLim = time.time() + 6
while time.time() < tLim:
try:
data, addr = sock.recvfrom(4096)
print(f"Received from {addr}: {data}")

except socket.timeout:
break

sock.close()

Эта проблема также возникает с библиотекой ssdpy в PyPi, что неудивительно, поскольку исходный код библиотеки аналогичен приведенной выше реализации.
Попытка решения
Я экспериментировал со всеми типами конфигураций Windows, которые только мог придумать (настройки брандмауэра, службы, разрешения, переключение сетей...), но безрезультатно. После поиска в Интернете я нашел метод, при котором отправленное сообщение M-Search больше не направляется на адрес 127.0.0.1, но я не могу получить ответ от устройства! С помощью Wireshark я вижу, что устройство отправляет ответ, но код его не читает. Хотя реализация БУДЕТ обнаруживать случайный трафик ssdp, который происходит в то же время в сети.

Код: Выделить всё

import socket
import struct
import time

local_ip = '192.168.20.48'
ssdp_addr = "239.255.255.250"
ssdp_port = 1900
searchterm = 'ssdp:all'

m_msg = f"""\
M-SEARCH * HTTP/1.1\r\n\
Host: {ssdp_addr}:{ssdp_port}\r\n\
Man: "ssdp:discover"\r\n\
ST: {searchterm}\r\n\
MX: 2\r\n\r\n""".encode("utf-8")

if __name__ == "__main__":
# Method 2
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sock.bind((local_ip, ssdp_port))

group = socket.inet_aton(ssdp_addr)
mreq = struct.pack('4s4s', group, socket.inet_aton(local_ip))
sock.setsockopt(socket.IPPROTO_IP, socket.IP_ADD_MEMBERSHIP, mreq)
sock.settimeout(5)

ret = sock.sendto(m_msg, (ssdp_addr, ssdp_port))

# CODE to listen for SSDP responses. This finds unrelated network upnp notifies, but
# does not get the response from the device.  I can see the response from the device is
# being sent with wireshark
tLim = time.time() + 6
while time.time() < tLim:
try:
data, addr = sock.recvfrom(4096)
print(f"Received from {addr}: {data}")

except socket.timeout:
break

sock.close()
С помощью этого метода Wireshark показывает M-SEARCH с источником/назначением = 192.168.20.48 / 239.255.255.250 и ответ от источника/назначения устройства = 192.168.30.82 / 192.168.20.48
Где 192.168.20.48 = локальный IP-адрес ПК, а 192.168.30.82 = локальный IP-адрес устройства.
Справка
Мне интересно, могу ли я внести изменения в любой из этих методов, чтобы они работали последовательно. Первый метод работает какое-то время, какое-то время. Вторая половина метода работает всегда. Я готов использовать модифицированную версию любого из этих методов или совершенно новую, если я совершенно на неправильном пути.

Подробнее здесь: https://stackoverflow.com/questions/792 ... on-windows
Реклама
Ответить Пред. темаСлед. тема

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

  • Похожие темы
    Ответы
    Просмотры
    Последнее сообщение

Вернуться в «Python»