Skip to content

jixiaoyong/flutter_ali_http_dns

Repository files navigation

Flutter Ali HTTP DNS 🚧

⚠️ 注意:本项目处于积极更新中,各项 API 可能会有变更。

一个基于阿里云 HTTPDNS的 Flutter 插件,提供智能域名解析和代理功能,支持 HTTP/1.1 和 HTTP/2 协议。

代码参考了Flutter接入移动解析HTTPDNS Android/iOS SDK实践方案和已经标记为discontinued(截止2025-09-01)的aliyun_httpdns

支持平台: Android、iOS

支持解析域名对应的 IP,也支持代理网络请求并解析域名。

网络请求示意图:

┌─────────────────────────────────────────────────────────────────────────────────┐
│                              Flutter App                                        │
│                                                                                 │
│  ┌─────────────┐  ┌─────────────┐  ┌─────────────┐  ┌─────────────┐           │
│  │   Dio       │  │ HttpClient  │  │   Other     │  │   Other     │           │
│  │  Client     │  │             │  │             │  │  Clients    │           │
│  └─────┬───────┘  └─────┬───────┘  └─────┬───────┘  └─────┬───────┘           │
│        │                │                │                │                   │
│        └────────────────┼────────────────┼────────────────┘                   │
│                         │                │                                    │
│                         ▼                ▼                                    │
│  ┌─────────────────────────────────────────────────────────────────────────────┐ │
│  │                    Local Proxy Server (localhost:4041)                      │ │
│  │                                                                             │ │
│  │  ┌─────────────────┐    ┌─────────────────┐    ┌─────────────────┐        │ │
│  │  │   Request       │    │   DNS Resolver  │    │   Response      │        │ │
│  │  │   Parser        │    │                 │    │   Forwarder     │        │ │
│  │  │                 │    │  ┌─────────────┐ │    │                 │        │ │
│  │  │ • 解析请求协议   │    │  │   Cache     │ │    │ • 转发响应      │        │ │
│  │  │ • 提取域名端口   │    │  │             │ │    │ • 错误处理      │        │ │
│  │  │ • 识别协议类型   │    │  │ • IP缓存    │ │    │ • 日志记录      │        │ │
│  │  └─────┬───────────┘    │  │ • TTL管理   │ │    └─────────────────┘        │ │
│  │        │                │  └─────┬───────┘ │                               │ │
│  │        ▼                │        ▼         │                               │ │
│  │  ┌─────────────────┐    │  ┌─────────────┐ │    ┌─────────────────┐        │ │
│  │  │   Protocol      │    │  │ HTTPDNS     │ │    │   Connection     │        │ │
│  │  │   Detector      │    │  │ Resolver    │ │    │   Manager        │        │ │
│  │  │                 │    │  │             │ │    │                 │        │ │
│  │  │ • HTTP/1.1      │    │  │ • 阿里云    │ │    │ • 连接管理       │        │ │
│  │  │ • HTTP/2        │    │  │   HTTPDNS   │ │    │ • 连接复用       │        │ │
│  │  │ • HTTPS         │    │  │ • 系统DNS   │ │    │ • 错误重试       │        │ │
│  │  │ • HTTP/2        │    │  │   回退      │ │    │ • 超时处理       │        │ │
│  │  └─────────────────┘    │  └─────────────┘ │    └─────────────────┘        │ │
│  └─────────────────────────┼──────────────────┘                               │ │
│                            │                                                  │ │
│                            ▼                                                  │ │
│  ┌─────────────────────────────────────────────────────────────────────────────┐ │
│  │                    Target Server Connection                                │ │
│  │                                                                             │ │
│  │  ┌─────────────────┐    ┌─────────────────┐    ┌─────────────────┐        │ │
│  │  │   Socket        │    │   Request       │    │   Response      │        │ │
│  │  │   Connection    │    │   Forwarding    │    │   Processing    │        │ │
│  │  │                 │    │                 │    │                 │        │ │
│  │  │ • 连接目标IP     │    │ • 修改Host头    │    │ • 接收响应       │        │ │
│  │  │ • 处理连接错误   │    │ • 转发原始请求   │    │ • 解析响应头     │        │ │
│  │  │ • 重试机制      │    │ • 保持请求头     │    │ • 转发给客户端   │        │ │
│  │  └─────────────────┘    └─────────────────┘    └─────────────────┘        │ │
│  └─────────────────────────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────────────────────┘
                                    │
                                    ▼
┌─────────────────────────────────────────────────────────────────────────────────┐
│                              Internet                                           │
│                                                                                 │
│  ┌─────────────┐  ┌─────────────┐  ┌─────────────┐  ┌─────────────┐           │
│  │   阿里云    │  │   目标      │  │   目标      │  │   目标      │           │
│  │  HTTPDNS    │  │   服务器1   │  │   服务器2   │  │   服务器N   │           │
│  │   服务      │  │   (API)     │  │   (CDN)     │  │   (静态)    │           │
│  │             │  │             │  │             │  │             │           │
│  │ • 域名解析   │  │ • 业务逻辑   │  │ • 内容分发   │  │ • 静态资源   │           │
│  │ • IP优化    │  │ • 数据处理   │  │ • 媒体流     │  │ • 图片文件   │           │
│  │ • 负载均衡   │  │ • 响应生成   │  │ • 缓存压缩   │  │ • CSS/JS    │           │
│  │ • 故障转移   │  │ • 数据库查询 │  │ • 边缘计算   │  │ • 文档下载   │           │
│  └─────────────┘  └─────────────┘  └─────────────┘  └─────────────┘           │
└─────────────────────────────────────────────────────────────────────────────────┘
📋 详细流程说明(点击展开)

1. 应用层请求

  • Flutter 应用中的各种 HTTP 客户端(Dio、HttpClient 等)发起网络请求
  • 请求被配置为通过本地代理服务器(localhost:4041)

2. 代理服务器处理

  • 请求解析器:解析 HTTP/HTTPS 请求,提取目标域名和端口
  • 协议检测器:自动识别请求协议类型(HTTP/1.1、HTTP/2、HTTPS)
  • DNS 解析器:使用阿里云 HTTPDNS 服务解析域名对应的 IP 地址

3. DNS 解析流程

  • 缓存检查:首先检查本地缓存中是否有有效的 IP 地址
  • HTTPDNS 解析:调用阿里云 HTTPDNS 服务进行域名解析
  • 系统 DNS 回退:如果 HTTPDNS 解析失败,自动回退到系统 DNS
  • 结果缓存:将解析结果缓存到本地,提升后续请求速度

4. 目标服务器连接

  • Socket 连接:使用解析得到的 IP 地址建立到目标服务器的连接
  • 请求转发:修改请求头中的 Host 信息,转发原始请求到目标服务器
  • 响应处理:接收目标服务器的响应,转发回客户端

5. 连接管理

  • 连接管理:管理 Socket 连接,支持连接复用和错误重试
  • 错误处理:处理网络错误、超时、重试等异常情况,返回布尔值而非抛出异常
  • 日志记录:记录详细的请求处理日志,便于调试和监控

6. 性能优化

  • 智能缓存:DNS 解析结果缓存,减少重复解析
  • 连接复用:复用 Socket 连接,减少连接建立开销
  • 协议优化:支持 HTTP/2 协议,提升传输效率
  • 负载均衡:利用阿里云 HTTPDNS 的基础负载均衡能力

功能特性

  • HTTPDNS 解析: 通过阿里云 HTTPDNS 服务解析域名,提升解析速度和准确性
  • 智能代理: 自动启动本地代理服务器,支持 HTTP/1.1 和 HTTP/2 协议
  • 端口管理: 智能端口分配和冲突处理,无需手动管理
  • 多客户端支持: 支持 Dio、HttpClient 等主流 HTTP 客户端,支持 HTTP/1.1 和 HTTP/2 协议
  • 智能缓存: 独立的缓存管理器,支持动态启用/禁用缓存,提升性能

快速开始

1. 添加依赖

方式一:GitHub 依赖(推荐)

dependencies:
  flutter_ali_http_dns:
    git:
      url: https://github.com/jixiaoyong/flutter_ali_http_dns
      ref: master # 或指定版本标签,如 v0.0.1

方式二:pub.dev 依赖(TODO:待发布到 pub.dev)

# TODO: 插件发布到 pub.dev 后使用此方式
dependencies:
  flutter_ali_http_dns: ^0.0.1

2. iOS 网络配置(重要!)

iOS 9+ 网络权限配置

如果你的应用需要支持 HTTP 协议(非HTTPS),必须在 ios/Runner/Info.plist 文件中添加以下配置:

<key>NSAppTransportSecurity</key>
<dict>
    <key>NSAllowsArbitraryLoads</key>
    <true/>
</dict>

3. 插件生命周期管理

最佳实践:启动时机和关闭时机

插件应该在用户同意隐私协议之后,第一次请求网络之前进行初始化, 在应用不再使用或退出时调用 dispose() 方法:

class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  late final FlutterAliHttpDns _dnsService;
  bool _isPrivacyAccepted = false;

  @override
  void initState() {
    super.initState();
    _dnsService = FlutterAliHttpDns();
  }

  /// 用户同意隐私协议后初始化插件
  Future<void> _initializeAfterPrivacyAccept() async {
    if (_isPrivacyAccepted) {
      await _dnsService.initialize(DnsConfig(
        accountId: 'your_account_id',
        accessKeyId: 'your_access_key_id',
        accessKeySecret: 'your_access_key_secret',
      ));
      print('DNS服务初始化完成');
    }
  }

  @override
  void dispose() {
    // 应用退出时清理资源
    _dnsService.dispose();
    super.dispose();
  }
}

3. 最简单的用法

仅域名解析(无需代理)

如果只需要域名解析功能,不需要代理服务器:

import 'package:flutter_ali_http_dns/flutter_ali_http_dns.dart';

// 1. 初始化DNS服务
final dnsService = FlutterAliHttpDns();
await dnsService.initialize(DnsConfig(
  accountId: 'your_account_id',
  accessKeyId: 'your_access_key_id',
  accessKeySecret: 'your_access_key_secret',
));

// 2. 解析域名(无需启动代理)
final ip = await dnsService.resolveDomain('www.example.com');
print('解析结果: $ip');

// 3. 应用退出时清理资源
@override
void dispose() {
  dnsService.dispose();
  super.dispose();
}

使用代理进行 HTTP 请求

// 1. 启动代理服务器(仅在需要代理时启动)
final success = await dnsService.startProxy();
if (success) {
  print('代理服务器启动成功');
} else {
  print('代理服务器启动失败');
}

// 2. 配置HttpClient使用代理
final client = HttpClient();
final success = await dnsService.configureHttpClient(client);
if (success) {
  print('HttpClient配置成功');
} else {
  print('HttpClient配置失败');
}

// 3. 发起请求
final request = await client.getUrl(Uri.parse('https://www.example.com'));
final response = await request.close();

// 4. 如果不再需要代理,可以停止代理服务器
// await dnsService.stopProxy();

进阶用法

1. 配置 Dio 客户端

import 'package:dio/dio.dart';
import 'package:dio/io.dart';

// 启动代理
final success = await dnsService.startProxy();
if (success) {
  print('代理服务器启动成功');
} else {
  print('代理服务器启动失败');
}

// 配置Dio使用代理
final dio = Dio();
final proxyConfig = await dnsService.getDioProxyConfig();

if (proxyConfig != null) {
  dio.httpClientAdapter = IOHttpClientAdapter(
    createHttpClient: () {
      final client = HttpClient();
      client.findProxy = (uri) => 'PROXY ${proxyConfig['host']}:${proxyConfig['port']}';
      return client;
    },
  );
}

// 发起请求
final response = await dio.get('https://www.example.com');

2. 自定义代理配置

SDK 会在本地启动一个代理服务器,转发网络请求,你可以配置这个代理服务器的端口范围,SDK 会优先遵循,但是如果指定限制下无法找到可用端口,也可能突破这个限制。

// 自定义端口池和端口范围
final proxyConfig = ProxyConfig(
  portPool: [4041, 4042, 4043],  // 优先使用的端口
  startPort: 4044,               // 自动分配起始端口
  endPort: 4050,                 // 自动分配结束端口
  enabled: true,
  host: 'localhost',
);

final success = await dnsService.startProxy(proxyConfig);
if (success) {
  print('代理服务器启动成功');
} else {
  print('代理服务器启动失败');
}

3. 高级 DNS 配置

配置属性参考云解析 DNS/解析服务/移动解析 HTTPDNS/开发参考

final dnsConfig = DnsConfig(
  accountId: 'your_account_id',
  accessKeyId: 'your_access_key_id',
  accessKeySecret: 'your_access_key_secret',
  enableCache: true,           // 启用缓存
  maxCacheSize: 1000,          // 最大缓存条目数
  maxNegativeCache: 30,        // 最大否定缓存时间(秒)
  enableSpeedTest: true,       // 启用测速
  timeout: 5,                  // 超时时间(秒)
  enableIPv6: false,           // 是否启用IPv6
  enableShort: false,          // 是否启用短连接
  preloadDomains: [           // 预加载域名
    'www.example.com',
    'api.example.com',
  ],
  keepAliveDomains: [         // 缓存保持域名
    'www.example.com',
  ],
  maxCacheTTL: 3600,          // 最大缓存TTL时间(秒)
  ispEnable: true,            // 启用ISP网络区分
  speedPort: 80,              // 测速端口
);

await dnsService.initialize(dnsConfig);

4. 智能缓存管理

插件提供了独立的缓存管理器,支持动态缓存控制:

// 检查缓存状态
bool isEnabled = dnsService.isCacheEnabled;
int currentSize = dnsService.cacheSize;
int maxSize = dnsService.maxCacheSize;

// 动态切换缓存状态
await dnsService.setEnableCache(false);  // 禁用缓存
await dnsService.setEnableCache(true);   // 启用缓存

// 清除缓存
await dnsService.clearCache();                    // 清除所有缓存
await dnsService.clearCache(['example.com']);     // 清除指定域名缓存

// 缓存状态监控
print('缓存状态: ${dnsService.isCacheEnabled ? "启用" : "禁用"}');
print('缓存使用: ${dnsService.cacheSize}/${dnsService.maxCacheSize}');

高级功能

1. 端口管理

// 获取当前使用的端口
final mainPort = await dnsService.getMainPort();
final allPorts = await dnsService.getActualPorts();

// 检查端口可用性
final isAvailable = await dnsService.isPortAvailable(4041);

// 获取代理地址
final proxyAddress = await dnsService.getProxyAddress();
final http2Address = await dnsService.getHttp2ProxyAddress();

2. 日志控制

// 设置日志级别
FlutterAliHttpDns.setLogLevel(LogLevel.info);

// 启用/禁用日志
FlutterAliHttpDns.setLogEnabled(true);

3. 代理状态管理

// 检查代理状态
final isRunning = dnsService.isProxyRunning;
final isInitialized = dnsService.isInitialized;

// 停止代理
final success = await dnsService.stopProxy();
if (success) {
  print('代理服务器已停止');
} else {
  print('停止代理服务器失败');
}

// 检查代理状态
final status = await dnsService.checkProxyStatus();

4. 生命周期管理

完整的应用生命周期示例

class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  late final FlutterAliHttpDns _dnsService;
  bool _isInitialized = false;
  bool _isProxyRunning = false;

  @override
  void initState() {
    super.initState();
    _dnsService = FlutterAliHttpDns();
  }

  /// 初始化DNS服务(在用户同意隐私协议后调用)
  Future<void> _initializeDns() async {
    try {
      final success = await _dnsService.initialize(DnsConfig(
        accountId: 'your_account_id',
        accessKeyId: 'your_access_key_id',
        accessKeySecret: 'your_access_key_secret',
      ));

      if (success) {
        setState(() => _isInitialized = true);
        print('DNS服务初始化成功');
      }
    } catch (e) {
      print('DNS服务初始化失败: $e');
    }
  }

  /// 启动代理服务器(仅在需要代理时调用)
  Future<void> _startProxy() async {
    if (!_isInitialized) {
      print('请先初始化DNS服务');
      return;
    }

    try {
      final success = await _dnsService.startProxy();
      if (success) {
        setState(() => _isProxyRunning = true);
        print('代理服务器启动成功');
      }
    } catch (e) {
      print('代理服务器启动失败: $e');
    }
  }

  /// 停止代理服务器
  Future<void> _stopProxy() async {
    try {
      final success = await _dnsService.stopProxy();
      if (success) {
        setState(() => _isProxyRunning = false);
        print('代理服务器已停止');
      } else {
        print('停止代理服务器失败');
      }
    } catch (e) {
      print('停止代理服务器失败: $e');
    }
  }

  @override
  void dispose() {
    // 应用退出时清理所有资源
    _dnsService.dispose();
    super.dispose();
  }
}

按需启动代理

class NetworkService {
  final FlutterAliHttpDns _dnsService = FlutterAliHttpDns();
  bool _isProxyStarted = false;

  /// 初始化DNS服务
  Future<void> initialize() async {
    await _dnsService.initialize(DnsConfig(
      accountId: 'your_account_id',
      accessKeyId: 'your_access_key_id',
      accessKeySecret: 'your_access_key_secret',
    ));
  }

  /// 按需启动代理(仅在需要代理时调用)
  Future<void> _ensureProxyStarted() async {
    if (!_isProxyStarted) {
      final success = await _dnsService.startProxy();
      if (success) {
        _isProxyStarted = true;
      }
    }
  }

  /// 使用代理发起HTTP请求
  Future<void> makeHttpRequest() async {
    await _ensureProxyStarted(); // 按需启动代理

    final client = HttpClient();
    final success = await _dnsService.configureHttpClient(client);
    if (success) {
      // 发起请求...
    } else {
      print('配置HttpClient失败');
    }
  }

  /// 仅解析域名(无需代理)
  Future<String> resolveDomain(String domain) async {
    return await _dnsService.resolveDomain(domain);
  }

  /// 清理资源
  void dispose() {
    _dnsService.dispose();
  }
}

5. 批量域名解析(无需代理)

// 批量解析域名,无需启动代理服务器
final domains = ['www.taobao.com', 'www.douyin.com', 'www.baidu.com'];
final results = <String, String>{};

for (final domain in domains) {
  try {
    final ip = await dnsService.resolveDomain(domain);
    results[domain] = ip;
    print('$domain -> $ip');
  } catch (e) {
    print('解析失败: $domain - $e');
  }
}

6. 系统DNS解析

当需要绕过HTTPDNS直接使用系统DNS解析时,可以使用 resolveWithSystemDns 方法:

// 使用系统DNS解析域名(默认只返回公网IP)
final ip = await dnsService.resolveWithSystemDns('www.example.com');
if (ip != null) {
  print('系统DNS解析结果: $ip');
} else {
  print('系统DNS解析失败');
}

// 对比HTTPDNS和系统DNS的解析结果
final httpDnsResult = await dnsService.resolveDomain('www.example.com');
final systemDnsResult = await dnsService.resolveWithSystemDns('www.example.com');

print('HTTPDNS结果: $httpDnsResult');
print('系统DNS结果: $systemDnsResult');

// 调试模式:获取所有IP地址(包括私有地址)
final allIps = await dnsService.resolveWithSystemDns('www.example.com', onlyPublicIp: false);
print('所有IP地址: $allIps');

参数说明:

  • domain: 要解析的域名
  • onlyPublicIp: 是否只返回公网IP地址,默认为 true
    • true: 过滤私有地址、回环地址、多播地址等,只返回可公网访问的IP
    • false: 返回所有解析到的IP地址,包括私有地址(用于调试)

使用场景:

  • 网络调试和对比测试
  • 当HTTPDNS服务不可用时
  • 需要验证域名解析结果的准确性
  • 特殊网络环境下的备选方案
  • 调试时获取完整的IP地址列表

API 参考

DNS 配置 (DnsConfig)

参数 类型 默认值 说明
accountId String - 阿里云账号 ID
accessKeyId String - 访问密钥 ID
accessKeySecret String - 访问密钥 Secret
enableCache bool true 是否启用缓存
maxCacheSize int 100 最大缓存大小
maxNegativeCache int 30 最大否定缓存时间(秒)
enableSpeedTest bool true 是否启用速度测试
timeout int 3 超时时间(秒)
enableIPv6 bool false 是否启用 IPv6
enableShort bool false 是否启用短连接
preloadDomains List<String> [] 预加载域名列表
keepAliveDomains List<String> [] 缓存保持域名列表
maxCacheTTL int 3600 最大缓存 TTL 时间(秒)
ispEnable bool true 是否启用 ISP 网络区分
speedPort int 80 测速端口

代理配置 (ProxyConfig)

参数 类型 默认值 说明
portPool List<int>? null 端口池(优先使用的端口列表)
startPort int? 4041 自动分配的起始端口
endPort int? startPort + 100 自动分配的结束端口
enabled bool true 是否启用代理
host String 'localhost' 代理主机

核心方法

初始化和配置

// 初始化DNS服务
Future<bool> initialize(DnsConfig config)

// 启动代理服务器
Future<bool> startProxy({ProxyConfig config = const ProxyConfig()})

// 停止代理服务器
Future<bool> stopProxy()

域名解析

// 解析域名,失败时返回原域名
Future<String> resolveDomain(String domain, {bool enableSystemDnsFallback = true})

// 解析域名,失败时返回null
Future<String?> resolveDomainNullable(String domain, {bool enableSystemDnsFallback = true})

// 使用系统DNS解析域名(绕过HTTPDNS),默认过滤非公网地址
Future<String?> resolveWithSystemDns(String domain, {bool onlyPublicIp = true})

缓存管理

// 动态开启或关闭缓存功能。此设置在服务初始化后依然可以随时修改。
Future<void> setEnableCache(bool enable)

// 清除缓存。不带参数时,清除所有域名的缓存;带参数时,清除指定域名列表的缓存。
Future<bool> clearCache([List<String>? hostNames])

// 检查缓存是否启用
bool get isCacheEnabled

// 获取当前缓存大小
int get cacheSize

// 获取最大缓存大小
int get maxCacheSize

代理管理

// 获取默认代理地址 (HTTP/1.1, HTTPS)
Future<String?> getProxyAddress()

// 获取HTTP/2代理地址
Future<String?> getHttp2ProxyAddress()

// 获取所有代理地址列表
Future<List<String>> getAllProxyAddresses()

// 获取代理配置字符串
Future<String?> getProxyConfigString()

// 获取Dio客户端所需的代理配置
Future<Map<String, dynamic>?> getDioProxyConfig()

// 检查代理服务器的运行状态
Future<bool> checkProxyStatus()

端口管理

// 获取主要端口(第一个端口)
Future<int?> getMainPort()

// 获取实际使用的端口列表
Future<List<int>> getActualPorts()

// 检查端口是否可用
Future<bool> isPortAvailable(int port)

客户端配置

// 为 HttpClient 配置代理
Future<bool> configureHttpClient(HttpClient client)

状态查询

// 检查是否已初始化
bool get isInitialized

// 检查代理是否正在运行
bool get isProxyRunning

// 获取当前代理服务器实例
ProxyServer? get currentProxyServer

日志管理

// 设置日志级别
static void setLogLevel(LogLevel level)

// 启用或禁用日志
static void setLogEnabled(bool enabled)

资源管理

// 清理资源(停止代理服务器并清理相关资源)
Future<void> dispose()

工作原理

1. 插件生命周期

  1. 初始化阶段: 调用initialize()方法,配置 DNS 服务
  2. 域名解析: 可以直接使用resolveDomain()进行域名解析,无需代理
  3. 代理启动: 按需调用startProxy()启动代理服务器
  4. 资源清理: 调用dispose()清理所有资源

2. DNS 解析流程

  1. HTTPDNS 解析: 优先使用阿里云 HTTPDNS 服务解析域名
  2. 系统 DNS 回退: 如果 HTTPDNS 解析失败,自动回退到系统 DNS
  3. 缓存机制: 解析结果会被缓存,提升后续请求速度

3. 代理服务器

  1. 按需启动: 仅在需要代理 HTTP 请求时才启动代理服务器
  2. 端口分配: 智能分配可用端口,自动处理端口冲突
  3. 协议支持: 支持 HTTP/1.1 和 HTTP/2 协议
  4. 请求转发: 将客户端请求转发到目标服务器

3. 端口分配策略

  1. 优先级 1: 使用配置的端口池中的端口
  2. 优先级 2: 使用配置的端口范围(startPort 到 endPort)
  3. 优先级 3: 自动寻找可用端口(突破配置范围)
  4. 冲突处理: 自动处理端口冲突

使用场景

1. 移动应用网络优化

  • 提升域名解析速度
  • 减少网络延迟
  • 提高应用响应速度

2. 多端统一网络处理

  • 统一 Android 和 iOS 的网络处理逻辑
  • 简化网络配置管理

3. 网络调试和测试

  • 本地代理便于网络调试
  • 支持多种 HTTP 客户端

示例项目

查看 example/ 目录获取完整的使用示例:

  • 基础测试 (basic_tests.dart): 域名解析、HttpClient、Dio 测试
  • HTTP/2 测试 (http2_tests.dart): HTTP/2 协议支持测试
  • 高级功能测试 (advanced_tests.dart): 端口管理、代理配置、性能测试、错误处理测试

运行示例

cd example
flutter pub get
flutter run

示例项目依赖说明

示例项目使用 path: ../ 依赖,因为它与插件在同一仓库中。如果您在自己的项目中使用,请参考上面的"添加依赖"部分,使用 GitHub 依赖方式。

常见问题

Q: 如何获取代理端口?

A: 使用getMainPort()获取默认代理端口,或使用getProxyAddress()获取代理地址。

Q: 如何处理端口冲突?

A: SDK 会自动处理端口冲突,如果指定端口被占用,会自动寻找下一个可用端口。

Q: 代理服务器会自动清理端口吗?

A: 是的,当调用stopProxy()时,所有端口都会被自动清理。

Q: 插件的连接管理方式是什么?

A: 插件提供基础的连接管理功能,包括连接复用和错误重试,确保网络请求的稳定性和性能。连接管理采用简化的实现方式,专注于核心的网络代理功能。

Q: 如何检查端口是否可用?

A: 使用isPortAvailable(int port)方法检查端口是否可用。

Q: 插件的负载均衡功能如何?

A: 插件利用阿里云 HTTPDNS 的基础负载均衡能力,通过智能的 IP 选择来提升网络请求的性能和稳定性。负载均衡功能主要依赖阿里云 HTTPDNS 服务的原生能力。

Q: 支持哪些 HTTP 客户端?

A: 支持 Dio、HttpClient 等主流 HTTP 客户端,支持 HTTP/1.1 和 HTTP/2 协议,也可以自定义配置其他客户端。目前主要专注于 HTTP/HTTPS 协议的支持。

Q: 什么时候应该初始化插件?

A: 建议在用户同意隐私协议之后,第一次请求网络之前进行初始化。这样可以确保在用户同意的情况下才开始网络活动。初始化后可以通过检查返回值来判断是否成功。

Q: 什么时候应该启动代理服务器?

A: 代理服务器应该按需启动。如果只需要域名解析功能,无需启动代理;只有在需要代理 HTTP 请求时才启动代理服务器。启动后可以通过检查返回值来判断是否成功。

Q: 什么时候应该调用 dispose()?

A: 在应用退出或不再使用插件时调用 dispose()方法,它会自动停止代理服务器并清理所有资源。

Q: 如果只做域名解析,需要启动代理吗?

A: 不需要。域名解析功能不需要代理服务器,只有 HTTP 请求代理才需要启动代理服务器。域名解析方法会返回解析结果或原域名,不会抛出异常。

Q: 如何使用系统DNS解析?

A: 使用 resolveWithSystemDns(String domain, {bool onlyPublicIp = true}) 方法可以直接使用系统DNS解析域名,绕过HTTPDNS服务。默认情况下只返回公网IP地址,过滤掉私有地址、回环地址等无效地址。设置 onlyPublicIp: false 可以获取所有IP地址用于调试。这个方法适用于网络调试、对比测试或当HTTPDNS服务不可用时的备选方案。解析成功返回IP地址,失败返回null。

开发指南

Git Hooks 设置

项目包含自动版本号同步的 Git hooks,确保 pubspec.yamlREADME.md 中的版本号始终保持一致。

安装 Hooks

# 安装 Git hooks(首次克隆项目后运行)
./scripts/install-hooks.sh

功能说明

  • 自动检测:当修改 pubspec.yaml 中的版本号时,会自动检查 README.md 中的版本号
  • 自动同步:如果版本号不一致,会自动同步并添加到当前提交中
  • 提交保护:如果同步失败,提交会被阻止

手动运行

# 手动检查版本号同步
./scripts/sync-version.sh

许可证

MIT License

About

Flutter 阿里云 HttpDNS 插件,提供智能域名解析和代理服务。Flutter plugin for Alibaba Cloud HttpDNS with intelligent domain resolution and proxy services.

Topics

Resources

License

Stars

2 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors