如何创建双栈 (v4+v6) python UDP 服务器?

How to create a dual-stack (v4+v6) python UDP server?

通过搜索 'python dual-stack',我发现 https://bugs.python.org/issue25667 where someone mentions that this was already resolved in https://bugs.python.org/issue17561. In the latter issue, one of the last messages 有用地提到了实施的解决方案是什么:

# IPv4 only
>>> socket.create_server(addr)  
# IPv6 only
>>> socket.create_server(addr, family=socket.AF_INET6)
# IPv4 + IPv6
>>> socket.create_server(addr, family=socket.AF_INET6, dualstack_ipv6=True)

但是,我一直在寻找通用的解决方案。或者更确切地说,我一直在寻找 UDP,但认为因为这是在 IP 层上,所以任何解决方案都是通用的。事实证明 create_server() 是 TCP-only。

手动绑定到 v4 和 v6 意味着我不能只调用 recvfrom() 并让它阻塞直到数据包进来,因为 v6 数据包可能会在 v4 上阻塞时排队recvfrom 调用,反之亦然。所以我想我需要使用线程?

在 python 3.x 中制作双栈 UDP 服务器的最佳方法是什么?对我来说,Linux 解决方案就足够了,但当然与平台无关的答案更好。

基本上,如何在双栈中写这个:

import socket

server_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
server_socket.bind(('0.0.0.0', 53))

while True:
    message, address = server_socket.recvfrom(1400)

至少在 Linux 下,创建 IPv6 套接字会侦听 IPv6 和 IPv4 连接。也就是说,给定此代码:

import socket
s = socket.socket(socket.AF_INET6, socket.SOCK_DGRAM)
s.bind(('::', 9090))
while True:
   message, address = s.recvfrom(1024)
   print(address, "says: ", message.decode())

我可以使用 IPv4 连接:

echo hello world | nc -u 127.0.0.1 9090

这导致:

('::ffff:127.0.0.1', 36694, 0, 0) says:  hello world

或者我可以使用 IPv6 连接:

echo hello world | nc -u ::1 9090

这导致:

('::1', 51880, 0, 0) says:  hello world