You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Windows下Python Socket实现SSDP搜索结果不稳定的问题求助

Windows下Python Socket实现SSDP搜索结果不稳定的问题求助

目标

我正在编写一个Python Windows应用程序,需要使用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()

这个问题在PyPi上的ssdpy库中也会出现,这并不奇怪,因为该库的源代码与上述实现类似。

尝试的解决方案

我已经尝试了各种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是PC本地IP,192.168.30.82是设备本地IP)。

求助

我想知道是否可以对这两种方法中的任何一种进行修改,使其能够持续正常工作。第一种方法有时有效,大多数时候无效;第二种方法始终能正确发送请求,但无法接收设备的响应。如果我的思路完全错误,我也愿意尝试全新的方法。

备注:内容来源于stack exchange,提问作者Tyler B

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.14 18:25:25