无法在未ping的情况下向UDP IPv6套接字发送数据

0 投票
2 回答
1722 浏览
提问于 2025-04-18 00:19

我正在写一个程序,用来通过IPv6的UDP端口向一个设备发送和接收数据。我的Python代码是在Windows 7平台上运行的,而这个设备是一个定制的硬件。我的电脑和设备是直接连接的,没有通过局域网。

这个程序有点问题。当我第一次尝试向设备发送消息时,发送失败。具体来说,从wireshark的视角来看,我根本没有看到消息发送到设备上。当我在命令行中用ping <ipv6_addr> -t来ping这个设备时,前1到2次尝试是失败的,之后就开始收到回应了。我停止ping操作,然后像之前一样尝试发送消息,这次成功了。wireshark现在显示所有的消息。如果我在相对短的时间内(大约10秒到2分钟之间)持续发送消息,程序就能正常工作。如果我等得太久,我的消息又会再次发送失败。如果我让ping程序持续ping设备,无论我发送消息的时间间隔多长,我的消息也能成功发送。以下是我的代码:

import socket

def connect(port):
    if socket.has_ipv6:  
        client = socket.socket(socket.AF_INET6, socket.SOCK_DGRAM)   
        client.bind(('', port))
        client.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        client.settimeout(0.25)

def send_data(addr, port, data):
    client.sendto(data, (addr, port))

def main_app():
    connect(10000)
    bin_data = binascii.a2b_hex('deadbeef')

    # Do some processing
    send_data(<ipv6_address>, 10000, bin_data)

我在网上搜索了一下,但没有找到关于这个问题是Python引起的还是其他原因的好线索,所以我想先从Python入手,看看能找到什么。

任何帮助都非常感谢!

2 个回答

0

这里有几个小提示:

  • 在调用 client.bind() 之前,先调用 client.setsockopt()

  • 当你用完这个 socket 时,一定要调用 socket.close() 来关闭它。

  • 我怀疑你遇到的 ping 和时间问题,可能是因为超时时间设置得太短,加上 NDP 缓存的原因。超时时间 0.25 可能对 NDP 解析 和数据传输来说太低了(也许你的嵌入式设备处理速度慢)。当你进行 ping 操作时,它会为你执行 NDP,并创建一个缓存信息,这样你就可以在应用中使用,而不会超出超时限制。

    我建议你试着把超时限制调高: client.settimeout(2)

1

经过一番查找,我觉得找到了我的问题所在。我在绑定的时候没有把运行Python的电脑的IP地址包含进去。所以我把上面的connect()函数改成了

def connect(self):
    # ... 
    client.bind(('fe80::', port))
    # ...

这样我的消息就能稳定地发送了。我对套接字编程还很陌生,有人能解释一下为什么这个修改有效吗?

谢谢

撰写回答