将IPv4和IPv6源地址绑定到python套接字

我有一个python应用程序,需要为IPv6连接选择一个特定的本地源地址,但可以使用"any" 0.0.0.0进行IPv4连接 . 但是应用程序在 socket.connect((host, port)) 中使用主机名允许 socket.connect() 从名称进行地址查找 .

那么,如果在调用 socket.connect() 之前我不知道是否会通过名称查找产生IPv4地址或IPv6地址,如何将特定的IPv6源地址和IPv4 "any"地址绑定到本地套接字?

现在我正在处理 socket.EAI_ADDRFAMILY 上的例外:

try:
    sock.bind(("2601:a2a0:a0aa:1d00:aeaa:aaff:aa6c:aaab",0))
    sock.connect((host, port))
except socket.gaierror, e:
    if e[0] == socket.EAI_ADDRFAMILY:
        sock.bind(("0.0.0.0",0))
        sock.connect((host, port))

但是,当然不能保证异常处理程序中的 socket.connect() 将主机解析为IPv4地址只是因为之前的 socket.connect() .

肯定有更好的办法 . 我怀疑这将是我必须自己实现地址查找和选择并传递地址,而不是名称 socket.connect() . 这样我就知道我在做本地地址绑定时 socket.connect() 是使用IPv4还是IPv6 . 但是,对于我来说,重新实现 socket.connect() 已经完成的名称解析和选择似乎很愚蠢 .

回答(1)

2 years ago

您不能将多个地址绑定到同一个套接字,也不能将两次绑定到同一个套接字 . 相反,你必须首先使用getaddrinfo解析地址,然后使用低级connect和你从getaddrinfo获得的sockaddr . getaddrinfo还会告诉您这是哪种类型的套接字,以便在必须连接到IPv6地址时可以绑定到IPv6地址 .