如何创建双堆栈(V4+ V6)Python UDP服务器?

发布于 2025-01-25 00:00:13 字数 1132 浏览 2 评论 0 原文

通过搜索“ python dual-stack”,我找到了 https://bugs.pys.python.org/issue256667 有人提到有人已经在上一条消息

# 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。

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

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

基本上,如何在dual-stack中写这篇文章:

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)

By searching for 'python dual-stack', I found 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 helpfully mentions what the implemented solution is:

# 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)

However, I was looking for a generic solution. Or rather, I was looking for UDP but figured that, because this is on the IP layer, any solution would be generic. It turns out that create_server() is TCP-only.

Binding to both v4 and v6 manually means I cannot just call recvfrom() and let it block until a packet comes in, because then a v6 packet might be queued while it's blocking on the v4 recvfrom call or vice versa. So I guess I need to use threading?

What is the best way to make a dual-stack UDP server in python 3.x? For me, a Linux solution would be sufficient, but of course platform-independent answers are even better.

Basically, how to write this in dual-stack:

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)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

热鲨 2025-02-01 00:00:13

至少在Linux下,为IPv6和IPv4连接创建IPv6插座。也就是说,给定以下代码:

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())

连接

echo hello world | nc -u 127.0.0.1 9090

我可以使用IPv4:哪个导致IPv4

('::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

At least under Linux, creating an IPv6 socket listens for both IPv6 and IPv4 connections. That is, given this code:

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())

I can connect using IPv4:

echo hello world | nc -u 127.0.0.1 9090

Which results in:

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

Or I can connect using IPv6:

echo hello world | nc -u ::1 9090

Which results in:

('::1', 51880, 0, 0) says:  hello world
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文