我之前使用下面的代码将IPv4地址绑定到Python套接字作为源IP地址。
import socket
true_socket = socket.socket
def bound_socket(*a, **k):
sock = true_socket(*a, **k)
sock.bind((sourceIP, 0))
return sock
socket.socket = bound_socket
以上代码是否适用于IPv6地址?如果没有,我如何绑定IPv6地址?
提前致谢!
答案 0 :(得分:6)
你可以尝试这个,为了得到一个IPV6地址,建议你使用socket.getaddrinfo
它将返回IPV4和IPV6的所有不同地址,你可以将它们全部绑定,或者只绑定你想要的地址/需要。
import socket
def bound_socket(*a, **k):
sock = socket.socket(*a, **k)
if socket.AF_INET6 in a:
if not socket.has_ipv6:
raise ValueError("There's no support for IPV6!")
else:
address = [addr for addr in socket.getaddrinfo(source_ip, None)
if socket.AF_INET6 == addr[0]] # You ussually want the first one.
if not address:
raise ValueError("Couldn't find ipv6 address for source %s" % source_ip)
sock.bind(address[0][-1])
else:
sock.bind((source_ip, 0))
return sock
答案 1 :(得分:3)
如果您真的想要一个广泛的解决方案,可以扩展您的解决方案以使用getaddrinfo()
:
import socket
l = socket.getaddrinfo(None, "", 0, socket.SOCK_STREAM, 0, socket.AI_PASSIVE)
for i in l: print i
这给出了
(2, 1, 6, '', ('0.0.0.0', 0))
(10, 1, 6, '', ('::', 0, 0, 0))
这些是您应该创建套接字的参数:
s = socket.socket(i[0], i[1], i[2])
if i[0] == AF_INET6: s.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_V6ONLY, 1)
s.bind(i[4])
现在您拥有与协议一样多的套接字,您可以使用它们。 (唉,IPV6_V6ONLY
在旧的Windows版本下不起作用......)
如果您要绑定给定的主机名/ IP,请执行
l = socket.getaddrinfo("mylocalIP", None, 0, socket.SOCK_STREAM, 0, socket.AI_PASSIVE)
它将为您选择正确的地址/协议系列:
>>> socket.getaddrinfo("::1", None, 0, socket.SOCK_STREAM, 0, socket.AI_PASSIVE)
[(10, 1, 6, '', ('::1', 0, 0, 0))]
>>> socket.getaddrinfo("127.0.0.1", None, 0, socket.SOCK_STREAM, 0, socket.AI_PASSIVE)
[(2, 1, 6, '', ('127.0.0.1', 0))]
>>> socket.getaddrinfo("localhost", None, 0, socket.SOCK_STREAM, 0, socket.AI_PASSIVE)
[(10, 1, 6, '', ('::1', 0, 0, 0)), (2, 1, 6, '', ('127.0.0.1', 0))]
>>> socket.getaddrinfo("192.168.1.32", None, 0, socket.SOCK_STREAM, 0, socket.AI_PASSIVE)
[(2, 1, 6, '', ('192.168.1.32', 0))]
等
2
vs 10
为AF_INET
与AF_INET6
; socket.AI_PASSIVE
表示您需要此地址bind()
。
答案 2 :(得分:2)
这应该可以解决问题......设置地址族。
import socket
s = socket.socket(family=socket.AF_INET6)
s.bind(('::1', 1234))