feat(core): 增强IPv6支持和优化功能

- 添加IPv6可用性检查,优化用户界面反馈。
- 实现IPv6检测方法,确保用户在启用IPv6时获得准确提示。
- 更新下载线程设置,修正aria2c参数以提高兼容性。
This commit is contained in:
欧阳淇淇
2025-08-02 16:12:19 +08:00
parent 291c471b9e
commit 1c749079a2
4 changed files with 127 additions and 20 deletions

View File

@@ -319,18 +319,18 @@ class CloudflareOptimizer:
success_message += f"IPv6: {self.optimized_ipv6}\n"
if hostname:
# 先清理可能存在的旧记录
# 先清理可能存在的旧记录(只清理一次)
self.hosts_manager.clean_hostname_entries(hostname)
success = False
# 应用优选IP到hosts文件
if ipv4_success:
success = self.hosts_manager.apply_ip(hostname, self.optimized_ip) or success
success = self.hosts_manager.apply_ip(hostname, self.optimized_ip, clean=False) or success
# 如果启用IPv6并且找到了IPv6地址也应用到hosts
if ipv6_success:
success = self.hosts_manager.apply_ip(hostname, self.optimized_ipv6) or success
success = self.hosts_manager.apply_ip(hostname, self.optimized_ipv6, clean=False) or success
if success:
msg_box = QtWidgets.QMessageBox(self.main_window)

View File

@@ -283,11 +283,25 @@ class UIManager:
self.ipv6_action = QAction("启用IPv6支持", self.main_window, checkable=True)
self.ipv6_action.setFont(menu_font)
# 检查IPv6是否可用
ipv6_available = self._check_ipv6_availability()
if not ipv6_available:
self.ipv6_action.setText("启用IPv6支持 (不可用)")
self.ipv6_action.setEnabled(False)
self.ipv6_action.setToolTip("未检测到可用的IPv6连接")
# 检查配置中是否已启用IPv6
config = getattr(self.main_window, 'config', {})
ipv6_enabled = False
if isinstance(config, dict):
ipv6_enabled = config.get("ipv6_enabled", False)
# 如果配置中启用了IPv6但实际不可用则强制禁用
if ipv6_enabled and not ipv6_available:
config["ipv6_enabled"] = False
ipv6_enabled = False
# 使用utils.save_config直接保存配置
from utils import save_config
save_config(config)
self.ipv6_action.setChecked(ipv6_enabled)
@@ -367,6 +381,104 @@ class UIManager:
self.dev_menu.addMenu(self.hosts_submenu) # 添加hosts文件选项子菜单
self.dev_menu.addAction(self.ipv6_action) # 添加IPv6支持选项
def _check_ipv6_availability(self):
"""检查IPv6是否可用
Returns:
bool: IPv6是否可用
"""
import socket
import subprocess
import sys
import re
# 方法1: 检查本地IPv6地址配置
def has_ipv6_address():
try:
# 尝试获取本机所有IPv6地址
addrs = socket.getaddrinfo(socket.gethostname(), None, socket.AF_INET6)
for addr in addrs:
# 检查是否是全局IPv6地址(非本地链路地址)
ipv6 = addr[4][0]
if not ipv6.startswith('fe80:') and not ipv6 == '::1':
print(f"检测到IPv6地址: {ipv6}")
return True
return False
except Exception as e:
print(f"获取IPv6地址时出错: {e}")
return False
# 方法2: 尝试创建IPv6套接字
def can_create_ipv6_socket():
try:
socket.socket(socket.AF_INET6, socket.SOCK_DGRAM)
return True
except Exception as e:
print(f"创建IPv6套接字失败: {e}")
return False
# 方法3: ping6测试(仅适用于Windows)
def can_ping_ipv6():
if sys.platform != 'win32':
return False
try:
# 尝试ping Cloudflare的IPv6地址
result = subprocess.run(
['ping', '-6', '-n', '1', '-w', '2000', '2606:4700:4700::1111'],
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
text=True,
creationflags=subprocess.CREATE_NO_WINDOW
)
# 检查是否ping成功
success = result.returncode == 0 and "回复" in result.stdout
if success:
print("IPv6 ping测试成功")
return success
except Exception as e:
print(f"IPv6 ping测试失败: {e}")
return False
# 方法4: 尝试TCP连接到公共IPv6服务器
def can_connect_ipv6_tcp():
# 尝试连接的IPv6服务器列表
ipv6_servers = [
('2606:4700:4700::1111', 53), # Cloudflare DNS
('2001:4860:4860::8888', 53), # Google DNS
]
for server, port in ipv6_servers:
try:
sock = socket.socket(socket.AF_INET6, socket.SOCK_STREAM)
sock.settimeout(2)
sock.connect((server, port))
sock.close()
print(f"成功连接到IPv6服务器: {server}:{port}")
return True
except Exception as e:
print(f"连接IPv6服务器{server}:{port}失败: {e}")
return False
# 运行所有检测方法
methods = [
has_ipv6_address,
can_create_ipv6_socket,
can_ping_ipv6,
can_connect_ipv6_tcp
]
for method in methods:
if method():
print(f"IPv6检测通过: {method.__name__}")
return True
print("所有IPv6检测方法均失败")
return False
def show_menu(self, menu, button):
"""显示菜单
@@ -565,21 +677,13 @@ class UIManager:
# 如果用户尝试启用IPv6检查系统是否支持IPv6
if enabled:
# 检查是否可以访问IPv6
import socket
ipv6_supported = False
try:
# 尝试创建一个IPv6套接字
socket.socket(socket.AF_INET6, socket.SOCK_DGRAM)
ipv6_supported = True
except Exception:
ipv6_supported = False
# 使用改进的IPv6检测方法
ipv6_available = self._check_ipv6_availability()
if not ipv6_supported:
if not ipv6_available:
msg_box = msgbox_frame(
f"错误 - {APP_NAME}",
"\n找不到IPv6地址您的系统可能不支持IPv6\n",
"\n未检测到可用的IPv6连接无法启用IPv6支持。\n\n请确保您的网络环境支持IPv6且已正确配置\n",
QMessageBox.StandardButton.Ok,
)
msg_box.exec()
@@ -591,7 +695,9 @@ class UIManager:
# 保存设置到配置
if hasattr(self.main_window, 'config'):
self.main_window.config["ipv6_enabled"] = enabled
self.main_window.save_config(self.main_window.config)
# 直接使用utils.save_config保存配置
from utils import save_config
save_config(self.main_window.config)
# 显示设置已保存的消息
status = "启用" if enabled else "禁用"

View File

@@ -333,7 +333,7 @@ class HostsManager:
print(f"清理hosts文件失败: {e}")
return False
def apply_ip(self, hostname, ip_address):
def apply_ip(self, hostname, ip_address, clean=True):
if not self.original_content:
if not self.backup():
return False
@@ -347,8 +347,9 @@ class HostsManager:
return False
try:
# 首先清理已有的同域名记录
self.clean_hostname_entries(hostname)
# 首先清理已有的同域名记录(如果需要)
if clean:
self.clean_hostname_entries(hostname)
# 然后添加新记录
lines = self.original_content.splitlines()

View File

@@ -204,7 +204,7 @@ class DownloadThread(QThread):
'--header', 'Sec-Fetch-Site: same-origin',
'--http-accept-gzip=true',
'--console-log-level=notice',
'--summary-interval=0.5', # 减小摘要间隔到0.5秒,提高进度更新频率
'--summary-interval=1', # 设置为最小整数值1秒原值0.5不被aria2c支持
'--log-level=notice',
'--max-tries=3',
'--retry-wait=2',