我想在python上创建Ipv6套接字,我这样做:
#!/usr/bin/env python
import sys
import struct
import socket
host = 'fe80::225:b3ff:fe26:576'
sa = socket.socket(socket.AF_INET6, socket.SOCK_DGRAM)
sa.bind((host , 50000))
但它失败了:
socket.error: (22, 'Invalid argument') ?
任何人都可以帮助我吗?谢谢!
我像这样重做它,但仍然无法正常工作
>>>host = 'fe80::225:b3ff:fe26:576'
>>>sa = socket.socket(socket.AF_INET6, socket.SOCK_DGRAM)
>>>res = socket.getaddrinfo(host, port, socket.AF_UNSPEC, socket.SOCK_DGRAM, 0, socket.AI_PASSIVE)
>>>family, socktype, proto, canonname, sockaddr = res[0]
>>>print sockaddr
('fe80::225:b3ff:fe26:576', 50001, 0, 0)
>>>sa.bind(sockaddr)
Traceback (most recent call last):
File "<stdin>", line 1, in ?
File "<string>", line 1, in bind
socket.error: (22, 'Invalid argument')
答案 0 :(得分:5)
问题分为两部分
第一期
你应该使用从getaddrinfo获得sockaddr的sa.bind(sockaddr)
>>> HOST = 'localhost'
>>> PORT = 50007
>>> res = socket.getaddrinfo(HOST, PORT, socket.AF_UNSPEC, socket.SOCK_DGRAM, 0, socket.AI_PASSIVE)
>>> family, socktype, proto, canonname, sockaddr = res[1]
>>> proto
17
>>> sockaddr
('fe80::1%lo0', 50007, 0, 1)
第二期
如果您查看
中套接字文档中提供的示例Socket接受三个参数
socket( [family[, type[, proto]]])
根据文件
Create a new socket using the given address family,
socket type and protocol number. The address family
should be AF_INET (the default), AF_INET6 or AF_UNIX.
The socket type should be SOCK_STREAM (the default),
SOCK_DGRAM or perhaps one of the other "SOCK_" constants.
The protocol number is usually zero and may be omitted in that case.
如果您使用getaddressinfo获取proto的值,则该值与默认值0不同
但是当我执行以下操作时,我得到了一个不同的协议值--17。 你可能也想调查一下。
当然socket.has_ipv6对我来说是真的。
答案 1 :(得分:3)
上面缺少的另一件事是fe80 :: *是链接本地地址。因此,如果没有作用域ID,你就无法在技术上使用它们。
以防万一没有收入, “link-local
”表示该地址只能用于特定链接,但结果是由于该地址在理论上是链接特定的,因此您可以在多个链接上使用相同的地址。
现在授予了在大多数情况下,通过将已经唯一硬件(EUI-48)地址生成链接本地地址,将其转换为EUI-64,然后翻转U / L位(see)但这不是生成链接本地地址的唯一方法,其他机制可能导致重新使用地址(我不认为有任何禁止这种情况)。所以现在你知道为什么它不起作用。
下一个问题是你如何解决它,或者而不是你在哪里获得范围ID。遗憾的是,这是不明显的。如果您阅读讨论“Scope
”的IPV6 RFC,您会发现它是以一般方式定义的。实际上,如果您在Linux(也可能是Windows / Mac?)中运行此代码,则可以使用接口索引。
请注意,nss-mdns目前存在一个错误,即返回.local名称,其范围ID始终为零,因此在Linux中使用.local名称基本上不起作用,除非您的代码已经找出范围ID并设置它本身。