尝试将Python套接字绑定到IPv6地址时出现无效参数错误

3

我正在尝试在Python中将我的套接字绑定到另一台虚拟机的地址,以便我可以嗅探两者交换的帧。这是我的代码:

    import socket

UDP_IP = "fe80:849b:21f4:624c:d70b"
UDP_PORT = 61627

sock = socket.socket(socket.AF_INET6, socket.SOCK_DGRAM)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEPORT, 1)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR,1)
sock.bind((UDP_IP, UDP_PORT))

while True:
    data, addr = sock.recvfrom(1024)
    print(data)

当我尝试运行Python时,会收到错误信息:

sock.bind((UDP_IP, UDP_PORT))
socket.error: [Error 22] Invalid argument

我做错了什么,提前感谢您!

1
该IPv6地址无效。 - Michael Hampton
为什么它无效? - Kamal
1
因为它没有必需的作用域 ID。 - Michael Hampton
1个回答

7

我猜你已经找到答案了,但是一开始看到你的代码里有两个问题:

  1. 在IPv6中,fe80::/10地址块被保留用于链路本地地址。这些地址仅对本地子网有效,因此它们要使用作用域后缀,如%eth0来指定正确的作用域,其中eth0是网络接口的名称,该IPv6地址有效。

所以,对于我的MacOS笔记本电脑,UDP_IP地址可能如下所示:

UDP_IP = "fe80:849b:21f4:624c:d70b%en0"
  1. 接下来,对于IPv4,指定(UDP_IP, UDP_PORT)元组是绝对有效的,但对于IPv6,该元组还应包含flow_info和scope_id字段。有时,flow_info和scope_id可能会被省略或遗漏:(UDP_IP,UDP_PORT,0,0)。它有时可能有效,但不是在代码中使用的正确方式。

因此,可以通过socket.getaddrinfo(IP,PORT)获取这些字段,它会返回每个地址族和socket_kind的元组列表。可以使用以下类似的方法进行过滤:

for ainfo in socket.getaddrinfo(UDP_IP, UDP_PORT):
    if ainfo[0].name == 'AF_INET6' and ainfo[1].name == 'SOCK_DGRAM':
        target_address = ainfo[4]
        break

sock.bind(target_address)

我不确定我是否正确书写了示例代码,因为我没有测试它,请在使用前检查它。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接