8

我以前使用下面的代码将 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 地址?

提前致谢!

4

3 回答 3

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
于 2012-06-13T03:52:59.783 回答
3

这应该可以解决问题...设置地址系列。

import socket
s = socket.socket(family=socket.AF_INET6)
s.bind(('::1', 1234))
于 2012-06-13T03:50:34.857 回答
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))]

等等

2vs10AF_INETvs. AF_INET6; socket.AI_PASSIVE表示您需要此地址进行bind()ing。

于 2012-06-27T14:58:47.740 回答