You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Requests会话中强制POST请求使用IPv6地址

强制Requests会话使用IPv6发送POST请求

先确认请求的IP版本

你之前用socket.gethostbyname()只能返回IPv4地址,这是因为该方法仅支持IPv4。要同时获取IPv4和IPv6地址,改用socket.getaddrinfo():

import socket
from urllib.parse import urlparse

url = "sample_ipv6_host.com/path/to/something"
hostname = urlparse(url).hostname

# 获取主机所有地址信息
addr_info = socket.getaddrinfo(hostname, None)
for info in addr_info:
    addr_family = "IPv4" if info[0] == socket.AF_INET else "IPv6"
    print(f"{addr_family} 地址: {info[4][0]}")

返回结果里,AF_INET对应IPv4,AF_INET6对应IPv6。

强制使用IPv6的三种方法

方法1:全局修改Socket地址优先级

在程序开头添加以下代码,让Python默认仅解析IPv6地址:

import socket

# 强制socket仅返回IPv6地址
socket.getaddrinfo = lambda host, port, family=0, type=0, proto=0, flags=0: \
    [(socket.AF_INET6, type, proto, '', (host, port))]

这种方法简单粗暴,会影响整个程序的socket操作,适合仅需IPv6的场景。

方法2:自定义适配器(推荐)

通过自定义Requests的HTTPAdapter,仅让目标会话强制使用IPv6,不影响其他操作:

import requests
import socket
from urllib3.connection import HTTPConnection, HTTPSConnection
from urllib3.connectionpool import HTTPConnectionPool
from urllib3.poolmanager import PoolManager

# 定义IPv6专用HTTP连接类
class IPv6HTTPConnection(HTTPConnection):
    def _new_conn(self):
        # 仅解析IPv6地址
        addrs = socket.getaddrinfo(self.host, self.port, socket.AF_INET6)
        if not addrs:
            raise socket.gaierror("未找到目标主机的IPv6地址")
        sock = socket.socket(socket.AF_INET6, socket.SOCK_STREAM)
        if self.timeout:
            sock.settimeout(self.timeout)
        sock.connect(addrs[0][4])
        return sock

# 定义IPv6专用HTTPS连接类
class IPv6HTTPSConnection(HTTPSConnection):
    def _new_conn(self):
        addrs = socket.getaddrinfo(self.host, self.port, socket.AF_INET6)
        if not addrs:
            raise socket.gaierror("未找到目标主机的IPv6地址")
        sock = socket.socket(socket.AF_INET6, socket.SOCK_STREAM)
        if self.timeout:
            sock.settimeout(self.timeout)
        sock.connect(addrs[0][4])
        return self._prepare_conn(sock)

# 定义对应连接池
class IPv6HTTPConnectionPool(HTTPConnectionPool):
    ConnectionCls = IPv6HTTPConnection

class IPv6HTTPSConnectionPool(HTTPConnectionPool):
    ConnectionCls = IPv6HTTPSConnection

# 定义池管理器
class IPv6PoolManager(PoolManager):
    def _new_pool(self, scheme, host, port, **kwargs):
        if scheme == "http":
            return IPv6HTTPConnectionPool(host, port, **kwargs)
        elif scheme == "https":
            return IPv6HTTPSConnectionPool(host, port, **kwargs)
        return super()._new_pool(scheme, host, port, **kwargs)

# 定义Requests适配器
class IPv6Adapter(requests.adapters.HTTPAdapter):
    def init_poolmanager(self, connections, maxsize, block=False, **pool_kwargs):
        self.poolmanager = IPv6PoolManager(num_pools=connections, maxsize=maxsize, block=block, **pool_kwargs)

# 使用会话挂载适配器
s = requests.Session()
# 为http和https请求挂载IPv6适配器
s.mount("http://", IPv6Adapter())
s.mount("https://", IPv6Adapter())

# 发送POST请求
url = "sample_ipv6_host.com/path/to/something"
r = s.post(url, data=data)

# 验证使用的IP地址
print(f"请求使用的IPv6地址: {r.raw._original_response.fp.raw._sock.getpeername()[0]}")

方法3:直接使用IPv6地址访问

如果你已经知道目标主机的IPv6地址,可直接在URL中用方括号包裹IPv6地址,例如:

url = "https://[2001:db8::1]/path/to/something"
r = s.post(url, data=data)

这种方法无需修改代码,前提是你已获取到目标的IPv6地址。

内容的提问来源于stack exchange,提问作者rachana acharya

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.04 23:27:11