【问题标题】:Windows doesn't receive multicast IPv6 packets from all interfacesWindows 不接收来自所有接口的多播 IPv6 数据包
【发布时间】:2018-04-27 02:36:09
【问题描述】:

我正在尝试使用此 python 2.7 代码在 Windows 上接收 IPv6 多播数据包(发送到 ff02::1 地址)-

import socket
import win_inet_pton
import struct

socket.IPPROTO_IPV6=41  #because using python 2.7 on wondows

PORT = 1234
UDP_BROADCAST_IPv6 = "ff02::1"

sock = socket.socket(socket.AF_INET6, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)

sock.bind(("",PORT)) # not working with "::" either

# Join multicast group
addrinfo = socket.getaddrinfo(UDP_BROADCAST_IPv6, None)[0]
group = socket.inet_pton(addrinfo[0], addrinfo[4][0])
mreq = group + struct.pack('@I', 0)
sock.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_JOIN_GROUP, mreq)

while True:
    msg=sock.recv(1024)
    print msg

我从另一台计算机发送数据包,该计算机通过以太网连接到我的计算机;另外,我的电脑也有WiFi接口。虽然我在使用 Wireshark 嗅探以太网连接时能够看到相关的数据包,但此代码没有接收到数据包。

但是,当我禁用 WiFi 网卡时,会收到数据包。 这让我觉得当 WiFi 接口启用时,代码只监听来自该接口的数据包。

我读到绑定到"" 应该能够接收来自所有网络接口的数据包,但由于某种原因它对我不起作用。

有人对我忘记做的事情有任何想法吗?或解决此问题的不同方法?

谢谢!

【问题讨论】:

  • 你的wifi有IPv4吗?还是您的以太网接口?为什么我要问是因为 IIRC,当您将 '' 作为要监听的地址时,python 基本上会执行 '0.0.0.0'。默认为 IPv4 地址。不确定情况是否如此,但我知道当 IPv6 是“新”时我遇到了问题:)
  • 以太网和 WiFi 都有 IPv4 和 IPv6。我也尝试绑定到"::",但也没有用。你最后绑定了什么地址?
  • 我的记忆力已经不像以前了,但我想我只是说f***它并从我的界面中删除了IPv4,只是为了隔离问题。
  • 之前我尝试取消 IPv4,但它对我不起作用。我终于设法找到了解决方案,但非常感谢您的帮助!

标签: python windows network-programming ipv6 multicast


【解决方案1】:

解决了:)

显然 IPv6 从所有接口监听多播。这个语法

mreq = group + struct.pack('@I', 0)

错了。根据this,mreq 由组 id 和接口 id 组成,其中 0 是默认接口(在我的例子中是 WiFi)。为了侦听来自其他接口的多播,应指定网络接口索引。

网络接口索引是运行ipconfig时ipv6地址中%后面出现的数字,也可以在cmd中运行“route print”找到。

我用这段代码在python上找到它:

import netifaces as ni
import _winreg as wr # use "winreg" in python3

def get_ethernet_ipv6_ifindex():
    x=ni.interfaces()
    con_names=get_connection_name_from_guid(x)
    ethernet_index= con_names.index('Ethernet')

    addresses= ni.ifaddresses(x[ethernet_index])
    brod_addr=addresses[socket.AF_INET6][-1]["broadcast"]

    return int(brod_addr[brod_addr.find("%")+1:])

"""
Taken from the very helpful https://stackoverflow.com/questions/29913516/how-to-get-meaningful-network-interface-names-instead-of-guids-with-netifaces-un
"""
def get_connection_name_from_guid(iface_guids):
    iface_names = ['(unknown)' for i in range(len(iface_guids))]
    reg = wr.ConnectRegistry(None, wr.HKEY_LOCAL_MACHINE)
    reg_key = wr.OpenKey(reg, r'SYSTEM\CurrentControlSet\Control\Network\{4d36e972-e325-11ce-bfc1-08002be10318}')
    for i in range(len(iface_guids)):
        try:
            reg_subkey = wr.OpenKey(reg_key, iface_guids[i] + r'\Connection')
            iface_names[i] = wr.QueryValueEx(reg_subkey, 'Name')[0]
        except WindowsError:
            pass
    return iface_names

然后-

mreq = group + struct.pack('@I', get_ethernet_ipv6_ifindex())

【讨论】:

  • 我试过了,但它不起作用。我没有看到任何 IPv6 多播数据包。知道为什么吗?
猜你喜欢
  • 2016-01-27
  • 1970-01-01
  • 2012-10-26
  • 1970-01-01
  • 1970-01-01
  • 2012-12-29
  • 2021-01-08
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多