python出现套接字创建不成功_具有IPv6地址的Python TCP套接字失败

我试图使用IPv6地址绑定python tcp套接字.

self.__addr = ('fe80::224:d7ff:fe9d:9800', 5050)

self.__type = socket.AF_INTE6

self.__sock = socket.socket(self.__type, socket.SOCK_STREAM)

for family, _, _, _, sockaddr in socket.getaddrinfo( self.__addr[0], self.__addr[1], 0, 0, socket.SOL_TCP ):

if family == self.__type:

self.__addr = sockaddr

break

self.__sock.bind( self.__addr )

self.__sock.listen(1)

我使用了其他解决方案中提到的socket.getaddrinfo()的结果,但始终出现此错误:

self.__sock.bind( self.__addr )

File "/usr/lib/python2.7/socket.py", line 224, in meth

return getattr(self._sock,name)(*args)

socket.error: [Errno 22] Invalid argument

这是我的网络接口的ifconfig结果

wlan0 Link encap:Ethernet Hardware Adresse 00:24:d7:9d:98:00

inet Adresse:192.168.0.103 Bcast:192.168.0.255 Maske:255.255.255.0

inet6-Adresse: fe80::224:d7ff:fe9d:9800/64

知道为什么会出现这个错误吗?

解决方法:

通常,网络前缀不会重叠,并且每个IP地址仅在单个接口上使用.但是对于链路本地,在启用IPv6的每个网络接口上使用(相同)前缀(fe80 :: / 10).这意味着,仅基于链路本地地址,系统无法确定要侦听的网络接口.您必须自己指定界面.

以字符串表示法编写地址时,可以通过将%后跟接口的ID附加到IPv6地址来实现.正如glglgl所示,这可能是例如FE80 :: 224:D7FF:fe9d:9800%为wlan0.接口名称取决于您所在的系统.我的OS X机器有接口en0和en1,我的Linux机箱有eth0,在Windows机器上接口名称是整数.

在套接字函数中,使用scope-id指定接口.这是地址元组的一部分.在你的例子中你使用(‘fe80 :: 224:d7ff:fe9d:9800’,5050).这很好,因为对于IPv6,可以省略最后两个元素.完整的地址元组是例如(‘fe80 :: 224:d7ff:fe9d:9800’,5050,0,4)其中4是范围ID.

您可以使用以下小脚本测试:

import socket

addrs = [('fe80::cafe:1%en0', 5050),

('fe80::cafe:1%en1', 5050)]

for addr in addrs:

print('Original addr: {}'.format(addr))

for res in socket.getaddrinfo(addr[0], addr[1], socket.AF_INET6,

socket.SOCK_STREAM, socket.SOL_TCP):

af, socktype, proto, canonname, sa = res

print('Full addr: {}'.format(sa))

print('')

在运行此脚本的系统上显示:

Original addr: ('fe80::cafe:1%en0', 5050)

Full addr: ('fe80::cafe:1%en0', 5050, 0, 4)

Original addr: ('fe80::cafe:1%en1', 5050)

Full addr: ('fe80::cafe:1%en1', 5050, 0, 5)

%之后的部分不再被套接字绑定使用,它依赖于scope-id.

这意味着以下绑定调用会产生相同的结果:

s = socket.socket(af, socktype, proto)

s.bind(('fe80::cafe:1', 5050, 0, 4))

s.bind(('fe80::cafe:1%en0', 5050, 0, 4))

s.bind(('fe80::cafe:1%bla', 5050, 0, 4))

最好使用从getaddrinfo获得的原始值.取决于这种未定义的行为不是一个好主意.像这样的简单循环应该是最好的:

addr = ('fe80::224:d7ff:fe9d:9800%wlan0', 5050)

s = None

for res in socket.getaddrinfo(addr[0], addr[1], socket.AF_INET6,

socket.SOCK_STREAM, socket.SOL_TCP):

af, socktype, proto, canonname, sa = res

try:

s = socket.socket(af, socktype, proto)

s.bind(sa)

s.listen(1)

except socket.error:

if s is not None:

s.close()

s = None

if s is None:

print('Socket opening/binding failed')

etc.

标签:python,linux,tcp,sockets,ipv6

来源: https://codeday.me/bug/20190708/1404270.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值