boxmoe_header_banner_img

Hello! 欢迎来到QwQのblog!

加载中

文章导读

ChmlFrp的第三方客户端


avatar
qwq 2026年3月7日 1.41k

下载链接:https://github.com/zhengyuliu047-rgb/ChmlFrp-flutter/releases

使用Flutter开发ChmlFrp桌面客户端:从零到一的实践指南

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。

前言

最近完成了一个个人项目——为ChmlFrp内网穿透服务开发一个Flutter图形化桌面客户端。这个项目让我深入实践了Flutter桌面端开发的全流程,在此将开发过程中的技术选型、实现细节和遇到的问题记录下来,希望能为对Flutter桌面开发感兴趣的开发者提供一些参考。

一、项目背景与技术选型

1.1 为什么选择Flutter?

在项目启动前,我对比了几个GUI框架选项:

  • Electron:成熟但资源占用较高
  • Qt:功能强大但学习曲线较陡
  • Flutter:一次编写多端部署,UI表现力强

最终选择Flutter 3.0+的主要原因:

  1. 跨平台潜力:虽然第一期只做Windows端,但未来可轻松扩展到macOS和Linux
  2. 开发效率:Hot Reload功能极大提升开发效率
  3. UI表现力:丰富的Material Design组件库,能构建现代化界面

1.2 开发环境配置

# 安装Flutter SDK
flutter channel stable
flutter upgrade

# 启用桌面支持
flutter config --enable-windows-desktop

# 创建项目
flutter create chmlfrp_flutter

二、项目架构设计

2.1 目录结构

chmlfrp_flutter/
├── lib/
│   ├── models/          # 数据模型
│   │   ├── user.dart    # 用户模型
│   │   ├── tunnel.dart  # 隧道模型
│   │   └── node.dart    # 节点模型
│   ├── pages/           # 页面组件
│   │   ├── login_page.dart
│   │   ├── tunnel_page.dart
│   │   └── settings_page.dart
│   ├── services/        # 服务层
│   │   ├── api_service.dart
│   │   ├── storage_service.dart
│   │   └── frpc_service.dart
│   ├── widgets/         # 自定义组件
│   │   ├── tunnel_card.dart
│   │   └── log_viewer.dart
│   └── main.dart        # 应用入口
├── windows/
│   └── frpc_integration/ # frpc集成模块
└── pubspec.yaml         # 依赖配置

2.2 状态管理方案

采用Provider + MVVM模式管理应用状态:

// lib/models/app_state.dart
class AppState with ChangeNotifier {
  User? _currentUser;
  List<Tunnel> _tunnels = [];
  bool _isLoading = false;
  
  User? get currentUser => _currentUser;
  List<Tunnel> get tunnels => _tunnels;
  bool get isLoading => _isLoading;
  
  Future<void> login(String username, String password) async {
    _isLoading = true;
    notifyListeners();
    
    try {
      final user = await ApiService.login(username, password);
      _currentUser = user;
      await StorageService.saveUser(user);
    } catch (e) {
      rethrow;
    } finally {
      _isLoading = false;
      notifyListeners();
    }
  }
}

三、核心功能实现

3.1 用户认证模块

// lib/services/api_service.dart
class ApiService {
  static const String _baseUrl = 'https://api.chmlfrp.cn';
  
  static Future<User> login(String username, String password) async {
    final response = await http.post(
      Uri.parse('$_baseUrl/auth/login'),
      body: jsonEncode({
        'username': username,
        'password': password,
      }),
      headers: {'Content-Type': 'application/json'},
    );
    
    if (response.statusCode == 200) {
      final data = jsonDecode(response.body);
      return User.fromJson(data['user']);
    } else {
      throw Exception('登录失败: ${response.body}');
    }
  }
}

3.2 隧道管理界面

// lib/pages/tunnel_page.dart
class TunnelPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('隧道管理'),
        actions: [
          IconButton(
            icon: Icon(Icons.add),
            onPressed: () => _showCreateDialog(context),
          ),
        ],
      ),
      body: Consumer<AppState>(
        builder: (context, appState, child) {
          if (appState.tunnels.isEmpty) {
            return Center(child: Text('暂无隧道,点击右上角+号创建'));
          }
          
          return ListView.builder(
            itemCount: appState.tunnels.length,
            itemBuilder: (context, index) {
              final tunnel = appState.tunnels[index];
              return TunnelCard(tunnel: tunnel);
            },
          );
        },
      ),
    );
  }
}

3.3 frpc进程集成(关键技术点)

这是项目的核心技术难点,需要Flutter与原生进程交互:

// windows/frpc_integration/frpc_manager.cpp
#include <windows.h>
#include <tchar.h>

class FrpcManager {
public:
    bool startFrpc(const std::string& configPath) {
        STARTUPINFO si;
        PROCESS_INFORMATION pi;
        
        ZeroMemory(&si, sizeof(si));
        si.cb = sizeof(si);
        ZeroMemory(&pi, sizeof(pi));
        
        std::string command = "frpc.exe -c " + configPath;
        
        if (!CreateProcess(
            NULL,
            const_cast<LPSTR>(command.c_str()),
            NULL,
            NULL,
            FALSE,
            CREATE_NO_WINDOW,
            NULL,
            NULL,
            &si,
            &pi
        )) {
            return false;
        }
        
        processHandle_ = pi.hProcess;
        return true;
    }
    
    bool stopFrpc() {
        if (processHandle_) {
            TerminateProcess(processHandle_, 0);
            CloseHandle(processHandle_);
            processHandle_ = NULL;
            return true;
        }
        return false;
    }
    
private:
    HANDLE processHandle_ = NULL;
};

对应的Flutter平台通道:

// lib/services/frpc_service.dart
class FrpcService {
  static const _platform = MethodChannel('com.chmlfrp/frpc');
  
  static Future<bool> startTunnel(String configPath) async {
    try {
      final result = await _platform.invokeMethod('startFrpc', {
        'configPath': configPath,
      });
      return result as bool;
    } on PlatformException catch (e) {
      print('启动失败: ${e.message}');
      return false;
    }
  }
  
  static Future<bool> stopTunnel() async {
    try {
      final result = await _platform.invokeMethod('stopFrpc');
      return result as bool;
    } on PlatformException catch (e) {
      print('停止失败: ${e.message}');
      return false;
    }
  }
}

四、遇到的问题与解决方案

4.1 中文乱码问题

在Windows端开发时,控制台输出中文出现乱码。解决方案:

  1. 修改系统区域设置(临时方案): chcp 65001
  2. 代码层面解决(推荐): // 在main函数中设置编码 void main() { // Windows控制台编码设置 if (Platform.isWindows) { final currentCodePage = _getConsoleOutputCP(); if (currentCodePage != 65001) { _setConsoleOutputCP(65001); // UTF-8 } } runApp(MyApp()); }

4.2 进程管理权限问题

在Windows上管理frpc进程需要处理UAC权限。解决方案:

<!-- windows/runner/Runner.manifest -->
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
  <trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
    <security>
      <requestedPrivileges>
        <requestedExecutionLevel
          level="asInvoker"
          uiAccess="false"/>
      </requestedPrivileges>
    </security>
  </trustInfo>
</assembly>

4.3 日志实时捕获

需要实时捕获frpc进程的输出日志:

// lib/widgets/log_viewer.dart
class LogViewer extends StatefulWidget {
  @override
  _LogViewerState createState() => _LogViewerState();
}

class _LogViewerState extends State<LogViewer> {
  final List<String> _logs = [];
  final _scrollController = ScrollController();
  
  @override
  void initState() {
    super.initState();
    _startLogListening();
  }
  
  Future<void> _startLogListening() async {
    const channel = EventChannel('com.chmlfrp/logs');
    channel.receiveBroadcastStream().listen((data) {
      setState(() {
        _logs.add(data.toString());
        if (_logs.length > 1000) _logs.removeAt(0);
        
        // 自动滚动到底部
        WidgetsBinding.instance.addPostFrameCallback((_) {
          if (_scrollController.hasClients) {
            _scrollController.animateTo(
              _scrollController.position.maxScrollExtent,
              duration: Duration(milliseconds: 300),
              curve: Curves.easeOut,
            );
          }
        });
      });
    });
  }
}

五、打包与发布

5.1 生成安装包

# 构建Release版本
flutter build windows --release

# 使用Inno Setup创建安装程序
# 安装脚本示例
[Setup]
AppName=ChmlFrp客户端
AppVersion=1.0.0
DefaultDirName={pf}\ChmlFrp
OutputDir=.\installer
OutputBaseFilename=ChmlFrp_Setup

[Files]
Source: "build\windows\runner\Release\*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs

5.2 依赖文件处理

需要将frpc.exe和相关依赖打包到安装程序中:

# 复制frpc可执行文件
cp third_party/frpc/windows_amd64/frpc.exe build/windows/runner/Release/

# 复制运行库
cp third_party/vcredist/*.dll build/windows/runner/Release/

六、项目总结

6.1 技术收获

  1. Flutter桌面开发:掌握了Flutter在Windows平台的完整开发流程
  2. 原生交互:深入理解了Platform Channels的工作原理
  3. 进程管理:学会了在桌面应用中管理外部进程的方法
  4. 状态管理:实践了Provider在复杂应用中的最佳实践

6.2 性能数据

  • 应用启动时间:< 2秒
  • 内存占用:~150MB(包含frpc进程)
  • UI帧率:稳定60fps

6.3 开源信息

七、未来规划

  1. 多平台支持:扩展macOS和Linux版本
  2. 功能增强:添加隧道分组、批量操作等功能
  3. 性能优化:减少内存占用,提升启动速度
  4. 插件系统:支持第三方插件扩展

结语

通过这个项目,我不仅完成了一个实用的工具,更深入掌握了Flutter桌面开发的各项技术。希望这篇分享能为正在探索Flutter桌面开发的开发者提供有价值的参考。开发过程中遇到的具体问题,欢迎在评论区交流讨论。


相关资源下载

注意事项

  1. 开发前请确保已安装Visual Studio 2019+和Windows 10 SDK
  2. 打包时注意处理UAC权限问题
  3. 发布前充分测试不同Windows版本的兼容性

如果可以的话来个star吧qwq

应用展示图片:



评论(5)

查看评论列表
评论头像
2026年03月07日
好使
评论头像
qwq 博主 2026年03月16日
1
评论头像
123 2026年03月18日
可以
评论头像
root 2026年03月18日
你好
评论头像
qwq 博主 2026年03月18日
可以

发表评论

表情 颜文字