首页 > 解决方案 > Python 的 recvfrom() 函数不返回任何数据

问题描述

我想先说一下我是网络新手,并且仍在学习我的 Python 技能,所以请放轻松。

我已经开始从事网络扫描项目,并尝试使用多种协议来尝试找到最适合我的目的的协议。SSDP 似乎对我来说是最好的,因此我一直在玩一个小小的通用即插即用脚本,我发现它可以尝试测试我的网络上的事情是如何工作的。

import socket  
import sys

dst = "239.255.255.250"  
st = "upnp:rootdevice"  
msg = [  
    'M-SEARCH * HTTP/1.1',
    'Host:239.255.255.250:1900',
    'Man:"ssdp:discover"',
    'MX:1',
    'ST:%s' % (st,),
    '']
    
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
s.bind((socket.gethostbyname(socket.gethostname()), 0))
print(s.getsockname())
s.settimeout(60)
byte_data = '\r\n'.join(msg) 
s.sendto(bytes(byte_data, 'utf-8'), (dst, 1900))
while True:  
    try:
        data, addr = s.recvfrom(32*1024)
    except socket.timeout:
        print("timeout has occurred")
        break
    print (f"$ {addr}\n{data}")
s.close() 

出于某种原因,这对我来说总是超时并且从不显示任何数据。在使用 WireShark 进行调查后,我可以看到我的计算机正在发送搜索并且设备正在将回复发送回我的计算机。有谁知道为什么会发生这种情况(操作系统是 Windows 10)。我会说我已经将超时时间增加到了很多次,但仍然没有通过。

标签: pythonpython-3.xsocketsupnpssdp

解决方案


正如评论中所指出的,M-SEARCH 请求标头中应该有一个额外的空白行,所以。

import socket
import sys

dst = "239.255.255.250"
st = "upnp:rootdevice"
msg = [
    'M-SEARCH * HTTP/1.1',
    'Host:239.255.255.250:1900',
    'Man:"ssdp:discover"',
    'MX:1',
    'ST:%s' % (st,),
    '',
    '']

s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
s.bind((socket.gethostbyname(socket.gethostname()), 0))
print(s.getsockname())
s.settimeout(2)
byte_data = '\r\n'.join(msg)
s.sendto(bytes(byte_data, 'utf-8'), (dst, 1900))
while True:
    try:
        data, addr = s.recvfrom(32 * 1024)
    except socket.timeout:
        print("timeout has occurred")
        break
    print(f"$ {addr}\n{data}")
s.close()

现在它起作用了。此外,将 SSDP MX 标头设置为 1 时,将超时设置为 60 是毫无意义的——任何响应请求的设备必须在 MX 秒内回复或根本不回复。

实际上,这在具有单个网络接口的系统上应该可以正常工作。但是在多宿主系统上,您需要通过将套接字绑定到该接口来在每个接口上发送请求,否则某些 UPNP 设备可能无法访问。


推荐阅读