Python3 IPv6多播
我试图用Python为IPv6多播通信设计一个简单的客户机/服务器对。到目前为止,我的代码似乎符合我在网上看到的示例,但我的服务器从未接收数据 我在Python3 IPv6多播,python,python-3.x,ipv6,multicast,Python,Python 3.x,Ipv6,Multicast,我试图用Python为IPv6多播通信设计一个简单的客户机/服务器对。到目前为止,我的代码似乎符合我在网上看到的示例,但我的服务器从未接收数据 我在ipmaddr show和netstat-g中看到订阅。tcpdump显示:10:13:36.913546 IP6(流标签0x77fe8,hlim 5,下一个报头UDP(17)有效负载长度:20)**省略**>ff16::fe.commplex-main:[UDP总和确定]UDP,长度12 客户端和服务器连接到同一交换机,IPv6单播地址位于同一子网
ipmaddr show
和netstat-g
中看到订阅。tcpdump显示:10:13:36.913546 IP6(流标签0x77fe8,hlim 5,下一个报头UDP(17)有效负载长度:20)**省略**>ff16::fe.commplex-main:[UDP总和确定]UDP,长度12
客户端和服务器连接到同一交换机,IPv6单播地址位于同一子网(它们可以相互ping)
服务器
#!/usr/bin/python3
import socket
import struct
local_addr = ::
mcast_addr = "ff16::fe"
mcast_port = 5000
ifn = "eno1"
# Create socket
sock = socket.socket(socket.AF_INET6, socket.SOCK_DGRAM)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEPORT, 1)
# Set multicast interface
ifi = socket.if_nametoindex(ifn)
ifis = struct.pack("I", ifi)
sock.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_MULTICAST_IF, ifis)
# Set multicast group to join
group = socket.inet_pton(socket.AF_INET6, mcast_addr) + ifis
sock.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_JOIN_GROUP, group)
sock_addr = socket.getaddrinfo(local_addr, mcast_port, socket.AF_INET6, socket.SOCK_DGRAM)[0][4]
sock.bind(sock_addr)
cmd = ""
while True:
data, src = sock.recvfrom(1024)
print("From " + str(src) + ": " + data.decode())
客户端
#!/usr/bin/python3
import socket
import struct
message = "Hello world!"
sock = socket.socket(socket.AF_INET6, socket.SOCK_DGRAM)
sock_addr = socket.getaddrinfo("ff16::fe", 5000, socket.AF_INET6, socket.SOCK_DGRAM)[0][4]
ttl = struct.pack('i', 5)
sock.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_MULTICAST_HOPS, ttl)
sock.sendto(message.encode(), sock_addr)
任何输入都将不胜感激。您不能使用“ff10::
作为IPv6多播地址。您在该地址中使用的范围0
,是保留的。IPv6多播要考虑多个RFC,使用标志和范围。例如,scope1
是接口本地作用域,发送到具有该作用域的组的流量不会离开发送主机上的本地接口
有关最新的作用域,请参见:
+------+--------------------------+-------------------------+
| scop | NAME | REFERENCE |
+------+--------------------------+-------------------------+
| 0 | Reserved | [RFC4291], RFC 7346 |
| 1 | Interface-Local scope | [RFC4291], RFC 7346 |
| 2 | Link-Local scope | [RFC4291], RFC 7346 |
| 3 | Realm-Local scope | [RFC4291], RFC 7346 |
| 4 | Admin-Local scope | [RFC4291], RFC 7346 |
| 5 | Site-Local scope | [RFC4291], RFC 7346 |
| 6 | Unassigned | |
| 7 | Unassigned | |
| 8 | Organization-Local scope | [RFC4291], RFC 7346 |
| 9 | Unassigned | |
| A | Unassigned | |
| B | Unassigned | |
| C | Unassigned | |
| D | Unassigned | |
| E | Global scope | [RFC4291], RFC 7346 |
| F | Reserved | [RFC4291], RFC 7346 |
+------+--------------------------+-------------------------+
编辑:
# Set multicast interface
ifi = socket.if_nametoindex(ifn)
ifis = struct.pack("I", ifi)
sock.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_MULTICAST_IF, ifis)
根据对原始问题的更改,您没有正确计算UDP校验和,这对于IPv4是可选的,但对于IPv6是必需的
此外,由于您正在创建自己的多播地址(不是IANA分配的地址),因此还应返回使用T
标志作为1
:
T=0表示永久分配的(“已知”)多播
地址,由互联网分配号码管理局(IANA)分配
T=1表示非永久性分配(“瞬态”或
“动态”分配的)多播地址
编辑2:
# Set multicast interface
ifi = socket.if_nametoindex(ifn)
ifis = struct.pack("I", ifi)
sock.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_MULTICAST_IF, ifis)
顺便说一下,您不能在IPv6多播中使用零地址:
保留多播地址:FF00:0:0:0:0:0:0
FF01:0:0:0:0:0:0
FF02:0:0:0:0:0:0:0
FF03:0:0:0:0:0:0:0
FF04:0:0:0:0:0:0
FF05:0:0:0:0:0:0:0
FF06:0:0:0:0:0:0
FF07:0:0:0:0:0:0
FF08:0:0:0:0:0:0
FF09:0:0:0:0:0:0:0
FF0A:0:0:0:0:0:0
FF0B:0:0:0:0:0:0
FF0C:0:0:0:0:0:0
FF0D:0:0:0:0:0:0
FF0E:0:0:0:0:0:0
FF0F:0:0:0:0:0:0:0
听起来,在尝试使用IPv6多播之前,您真的、真的需要研究RFC。除了所有其他好的建议之外:将服务器上的套接字绑定到链接本地地址。这将过滤传入的数据包,以便只有具有该目标地址的数据包才能到达您的代码。发送到多播地址的数据包将被丢弃。尝试绑定到::并确保在继续进行更复杂的操作之前能够正常工作。我还必须在客户端设置多播接口。客户机和服务器都有一个虚拟接口和一个可操作的VLAN感知接口(我无法进入网络驱动程序的设计)。我将两者上的接口设置为可操作的VLAN感知接口 在客户端上:
# Set multicast interface
ifi = socket.if_nametoindex(ifn)
ifis = struct.pack("I", ifi)
sock.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_MULTICAST_IF, ifis)
这似乎允许程序开始发送数据包,但是服务器仍然没有接收到它。带有-vv的tcpdump显示:
>ff06::.5000:[错误的udp校验和0xb590->0xf470!]UDP,长度12
,我已经更新了问题,感谢您的关注。再次感谢,我已经修改了我的代码以使用正确的多播地址。问题是UDP校验和哪里出错了?我不确定,我看不出它在哪里计算。校验和似乎不再是问题。客户端和服务器在同一网络上吗?无法通过Internet路由多播数据包。客户端和服务器在同一网络上。“客户端和服务器在同一网络上。”然后,您应该使用链接本地作用域:ff12::fe
。您似乎仍然错误地计算UDP校验和。"IPv4和IPv6使用UDP的关键区别在于,由于缺少IPv6报头校验和,RFC 2460强制使用计算出的UDP校验和,即非零值。校验和计算中包含的伪报头提供了一种统计检查,确保数据报已传递到预定的IPv6目标节点。[RFC1071]中描述了校验和计算的算法。"在这种情况下,未分配的作用域是否应该与链接本地作用域一样有效?就UDP校验和而言,我还需要在代码中做些什么?根据RFC,您应该能够使用未分配的作用域,但我不会,因为它可能会在某个点被重新定义,例如,直到这个RFC,领域本地被取消分配,现在您在尝试使用该作用域时可能会遇到麻烦。Admin Local对于您自己的使用非常常见。将其更改为:,仍然没有骰子。服务器计算机上的跟踪没有看到任何内容,发送计算机:10:13:36.913546 IP6(flowlabel 0x77fe8,hlim 5,下一个标头UDP(17)有效负载长度:20)**省略**>ff16::fe.commplex-main:[udp sum ok]udp,长度12
由于某些原因,校验和现在似乎正常了……我将在帖子中添加有关网络设置的更多详细信息。这可能也是代码的问题。感谢您的关注。