使用 Qt GRPC 构建高效的 Trojan-Go 客户端:详细指南

  • 使用 Qt GRPC 构建高效的 Trojan-Go 客户端:详细指南
    • 初识 Qt 和 gRPC
      • 什么是 Qt?
      • 什么是 gRPC?
    • 项目结构概述
    • 创建 proto 文件定义 API
      • 下载 api.proto 文件
      • 解析 proto 文件
        • 1. packageoption 语句
        • 2. 消息类型定义
          • Traffic
          • Speed
          • User
          • UserStatus
          • GetTrafficRequestGetTrafficResponse
          • ListUsersRequestListUsersResponse
          • GetUsersRequestGetUsersResponse
          • SetUsersRequestSetUsersResponse
        • 3. 服务定义
          • TrojanClientService
          • TrojanServerService
    • 配置 CMake 构建系统
      • CMake 配置解析
    • 实现 Trojan-Go 客户端
      • main.cpp 内容
      • 代码详解
      • 使用定时器实现数据流量和速度监控
    • 总结

在这里插入图片描述
trojan-go client
在这里插入图片描述

使用 Qt GRPC 构建高效的 Trojan-Go 客户端:详细指南

在上一篇 使用gRPC C++创建动态库以获取Trojan-go客户端的流量和速度信息 文章中使用纯 C++,这次随着 qt6.8 lts 发布,Qt GRPC 作为稳定模块推出,借此机会使用 Qt GRPC 实现该功能。

初识 Qt 和 gRPC

什么是 Qt?

Qt 是一个跨平台的 C++ 框架,用于开发图形界面和非图形界面应用。它提供了丰富的库支持、良好的跨平台兼容性、自动化的信号槽机制,使得在大型应用程序中管理事件和响应更为便捷。在本文中,Qt 提供了自动化工具来简化 Protobuf 和 gRPC 的代码生成,并结合 Qt 的 gRPC 模块,使得构建 gRPC 客户端更加便捷。

什么是 gRPC?

gRPC 是一种高性能的 RPC 框架,由 Google 开发,用于实现不同语言之间的服务调用。其基于 HTTP/2 协议,利用 Protocol Buffers(Protobuf)作为接口描述语言来定义服务和数据结构,允许客户端和服务器之间的轻量化通信。gRPC 的优势在于它的跨平台支持、灵活性和良好的性能,广泛应用于微服务架构和物联网领域。


项目结构概述

在创建项目之前,我们先来定义项目的目录结构,以确保文件结构清晰、便于管理:

trojan-go
├── api.proto          # Protobuf 文件,用于定义 gRPC 服务和消息格式
├── CMakeLists.txt     # CMake 构建文件,配置了编译选项、依赖项
└── main.cpp           # 主程序文件,实现客户端功能
  • api.proto:包含 API 的 gRPC 服务定义和数据结构。
  • CMakeLists.txt:配置 CMake 构建系统。
  • main.cpp:实现了 Trojan-Go 客户端的主要逻辑。

强制依赖 protoc.exe ,需要添加到环境变量中,从 https://github.com/protocolbuffers/protobuf/releases/download/v28.3/protoc-28.3-win64.zip 下载。


创建 proto 文件定义 API

proto 文件定义了客户端与服务器之间的通信规则。我们将在 api.proto 文件中定义数据结构和 gRPC 服务接口,确保客户端和服务器之间能够准确传递数据。

下载 api.proto 文件

下载 trojan-go api.proto 文件,文件内容如下:

syntax = "proto3";

package trojan.api;
option go_package = "github.com/p4gefau1t/trojan-go/api/service";

message Traffic {
    uint64 upload_traffic = 1;
    uint64 download_traffic = 2;
}

message Speed {
    uint64 upload_speed = 1;
    uint64 download_speed = 2;
}

message User {
    string password = 1;
    string hash = 2;
}

message UserStatus {
    User user = 1;
    Traffic traffic_total = 2;
    Speed speed_current = 3;
    Speed speed_limit = 4;
    int32 ip_current = 5;
    int32 ip_limit = 6;
}

message GetTrafficRequest {
    User user = 1;
}

message GetTrafficResponse {
    bool success = 1;
    string info = 2;
    Traffic traffic_total = 3;
    Speed speed_current = 4;
}

message ListUsersRequest {

}

message ListUsersResponse {
    UserStatus status = 1;
}

message GetUsersRequest {
    User user = 1;
}

message GetUsersResponse {
    bool success = 1;
    string info = 2;
    UserStatus status = 3;
}

message SetUsersRequest {
    enum Operation {
        Add = 0;
        Delete = 1;
        Modify = 2;
    }
    UserStatus status = 1;
    Operation operation = 2;
}

message SetUsersResponse {
    bool success = 1;
    string info = 2;
}

service TrojanClientService {
    rpc GetTraffic(GetTrafficRequest) returns(GetTrafficResponse){}
}

service TrojanServerService {
    // list all users
    rpc ListUsers(ListUsersRequest) returns(stream ListUsersResponse){}
    // obtain specified user's info
    rpc GetUsers(stream GetUsersRequest) returns(stream GetUsersResponse){}
    // setup existing users' config
    rpc SetUsers(stream SetUsersRequest) returns(stream SetUsersResponse){}
}
解析 proto 文件

这个 api.proto 文件定义了用于 Trojan API 的 gRPC 服务和消息结构,描述了客户端与服务器之间的通信模式。以下是该文件的详细解释:

1. packageoption 语句
package trojan.api;
option go_package = "github.com/p4gefau1t/trojan-go/api/service";
  • package 声明了 proto 文件的包名,trojan.api 用于在生成的代码中作为命名空间。
  • option go_package 定义了用于 Go 语言生成代码的包名,便于 Go 项目中导入。
2. 消息类型定义
Traffic
message Traffic {
    uint64 upload_traffic = 1;
    uint64 download_traffic = 2;
}
  • Traffic 消息定义了用户的上传和下载流量,字段类型为 uint64 表示无符号 64 位整数,适合表示较大的流量数据。
Speed
message Speed {
    uint64 upload_speed = 1;
    uint64 download_speed = 2;
}
  • Speed 消息记录了上传和下载速度,同样使用 uint64 类型来表示。
User
message User {
    string password = 1;
    string hash = 2;
}
  • User 消息包含用户的密码和哈希值,用于用户身份验证或标识。
UserStatus
message UserStatus {
    User user = 1;
    Traffic traffic_total = 2;
    Speed speed_current = 3;
    Speed speed_limit = 4;
    int32 ip_current = 5;
    int32 ip_limit = 6;
}
  • UserStatus 消息表示用户的状态信息,包含用户数据 (User)、总流量 (Traffic)、当前和限制速度 (Speed)、当前和限制的 IP 数量。
GetTrafficRequestGetTrafficResponse
message GetTrafficRequest {
    User user = 1;
}

message GetTrafficResponse {
    bool success = 1;
    string info = 2;
    Traffic traffic_total = 3;
    Speed speed_current = 4;
}
  • GetTrafficRequest 包含 User 数据,用于请求流量信息。
  • GetTrafficResponse 返回请求状态 success、信息 info,以及流量数据和速度数据。
ListUsersRequestListUsersResponse
message ListUsersRequest {}

message ListUsersResponse {
    UserStatus status = 1;
}
  • ListUsersRequest 不含字段,用于请求用户列表。
  • ListUsersResponse 返回每个用户的状态信息。
GetUsersRequestGetUsersResponse
message GetUsersRequest {
    User user = 1;
}

message GetUsersResponse {
    bool success = 1;
    string info = 2;
    UserStatus status = 3;
}
  • GetUsersRequest 请求特定用户的信息。
  • GetUsersResponse 返回状态 success、信息 info 和用户状态 UserStatus
SetUsersRequestSetUsersResponse
message SetUsersRequest {
    enum Operation {
        Add = 0;
        Delete = 1;
        Modify = 2;
    }
    UserStatus status = 1;
    Operation operation = 2;
}

message SetUsersResponse {
    bool success = 1;
    string info = 2;
}
  • SetUsersRequest 包含 UserStatusOperation,用于增加、删除或修改用户。
  • SetUsersResponse 返回操作状态 success 和相关信息 info
3. 服务定义
TrojanClientService
service TrojanClientService {
    rpc GetTraffic(GetTrafficRequest) returns(GetTrafficResponse){}
}
  • 定义 GetTraffic RPC 方法,允许客户端请求其流量信息。
TrojanServerService
service TrojanServerService {
    // list all users
    rpc ListUsers(ListUsersRequest) returns(stream ListUsersResponse){}
    // obtain specified user's info
    rpc GetUsers(stream GetUsersRequest) returns(stream GetUsersResponse){}
    // setup existing users' config
    rpc SetUsers(stream SetUsersRequest) returns(stream SetUsersResponse){}
}
  • TrojanServerService 包含 3 个方法:
    • ListUsers:返回用户列表,使用数据流式响应。
    • GetUsers:获取特定用户信息,支持流式请求和响应。
    • SetUsers:修改用户信息,通过流式请求和响应实现。

这个 api.proto 文件定义了 Trojan API 的服务与数据结构,支持流量查询、用户信息获取、用户列表和配置管理等功能。


配置 CMake 构建系统

接下来在 CMakeLists.txt 文件中配置 CMake,以便编译和链接所需的库和依赖。

cmake_minimum_required(VERSION 3.16)
project(trojan-go LANGUAGES CXX)

set(CMAKE_AUTOUIC ON)
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC ON)

set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

find_package(QT NAMES Qt6 Qt5 REQUIRED COMPONENTS Core Protobuf Grpc)
find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Core Protobuf Grpc)

add_executable(client main.cpp)

qt_add_protobuf(client
    PROTO_FILES
        api.proto
)

qt_add_grpc(client CLIENT
    PROTO_FILES
        api.proto
)

include(GNUInstallDirs)
install(TARGETS client
    LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
    RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
)
CMake 配置解析
  • qt_add_protobufqt_add_grpc 用于生成 Protobuf 和 gRPC 的 C++ 代码。
  • install 指定安装路径,将可执行文件安装到系统的标准目录。

实现 Trojan-Go 客户端

main.cpp 文件实现了客户端的主要逻辑,负责与服务器通信并处理流量信息。

main.cpp 内容
#include <QCoreApplication>
#include <QTimer>
#include <memory>
#include "api.qpb.h"
#include "api_client.grpc.qpb.h"
#include <QGrpcHttp2Channel>
#include <QGrpcChannelOptions>
#include <QGrpcStatus>
#include <QGrpcCallReply>

int main(int argc, char *argv[]) {
    QCoreApplication a(argc, argv);

    trojan::api::TrojanClientService::Client client;

    QGrpcChannelOptions channelOptions;
    QUrl clientApi = QUrl("http://127.0.0.128:10000"/*用户设定的 trojan-go api 地址和端口*/, QUrl::StrictMode);
    std::shared_ptr<QGrpcHttp2Channel> channel = std::make_shared<QGrpcHttp2Channel>(clientApi, channelOptions);

    if(client.attachChannel(channel)) {
        qDebug() << "attachChannel success";
    } else {
        qDebug() << "attachChannel failed";
    };

    QTimer timer;
    QObject::connect(&timer, &QTimer::timeout, &a, [&]() {
        trojan::api::User user;
        user.setPassword("trojan-go.com"/*用户连接服务器的密码*/);
        trojan::api::GetTrafficRequest req;
        req.setUser(user);

        std::unique_ptr<QGrpcCallReply> reply = client.GetTraffic(req);
        auto *replyPtr = reply.get();
        QObject::connect(
          replyPtr,
          &QGrpcCallReply::finished,
          &a,
          [reply = std::move(reply)](const QGrpcStatus &status) {
              if(!status.isOk()) {
                  qDebug() << "Failed to send message: " << status;
              } else {
                  trojan::api::GetTrafficResponse response;
                  if(reply->read(&response)) {
                      qDebug() << "Success:" << response.success();
                      qDebug() << "Info:" << response.info();
                      double downloadTrafficMB = response.trafficTotal().downloadTraffic() / 1024.0 / 1024.0;
                      double uploadTrafficMB   = response.trafficTotal().uploadTraffic() / 1024.0 / 1024.0;
                      double downloadSpeedMBps = response.speedCurrent().downloadSpeed() / 1024.0 / 1024.0;
                      double uploadSpeedMBps   = response.speedCurrent().uploadSpeed() / 1024.0 / 1024.0;

                      qDebug() << QString("Download Traffic: %1 MB").arg(downloadTrafficMB, 0, 'f', 2);
                      qDebug() << QString("Upload Traffic: %1 MB").arg(uploadTrafficMB, 0, 'f', 2);
                      qDebug() << QString("Download Speed: %1 MB/s").arg(downloadSpeedMBps, 0, 'f', 2);
                      qDebug() << QString("Upload Speed: %1 MB/s").arg(uploadSpeedMBps, 0, 'f', 2);
                      qDebug() << "";
                  } else {
                      qDebug() << "Failed to parse GetTrafficResponse.";
                  }
              }
          },
          Qt::SingleShotConnection);
    });

    timer.start(500);
    return a.exec();
}
代码详解
  • 连接服务器:使用 QGrpcHttp2Channel 通过 HTTP/2 连接到服务器。
  • 定时器监控:每 500 毫秒发送一次 GetTraffic 请求以获取最新流量和速度统计数据。
  • 结果解析和输出:解析服务器返回的流量数据并输出到控制台。
使用定时器实现数据流量和速度监控

通过 Qt 的 QTimer 实现客户端定时请求服务器流量和速度统计数据并进行处理。在实际应用中,定时更新数据可以实时监控服务器的状态,有助于及时获取连接信息并检测异常。


总结

本文介绍了如何使用 Qt 和 gRPC 实现一个高效的 Trojan-Go 客户端。从环境配置、Protobuf 文件定义、CMake 构建配置到主程序逻辑,我们全面讲解了客户端实现的每一步骤。借助 Qt 和 gRPC 的自动化工具,开发者能够更高效地实现客户端应用,同时享受 gRPC 高效的通信和 Qt 的跨平台支持。这一项目展示了 gRPC 的强大应用场景,也为开发更复杂的网络应用打下了基础。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/903125.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

利用Django实现MySQL数据库的内容在网页的增删改写

利用Django实现MySQL数据库的内容在网页的增删改写 1.建立项目2.定义模型3.创建视图4.创建模板5.创建表单和配置url6.最后修改7.效果 1.建立项目 输入命令django-admin startproject aaa 新建项目&#xff0c;项目名称命名为aaa&#xff0c;打开aaa文件夹&#xff0c;命令提示…

vscode 安装教程

双击vscode 安装包 同意&#xff0c;下一步 可以使用默认安装路径&#xff0c;也可以优化为这个 全选 取消勾选&#xff0c;点完成 在桌面创建一个空文件夹&#xff0c;拖动到vscode图标上 点击这个图标创建文件&#xff0c;注意必须以.py 结尾&#xff01;&#xff0…

第三十二篇:TCP协议粘包和滑动窗口,TCP系列七

上一篇《第三十一篇&#xff1a;TCP协议如何解决丢包的问题&#xff0c;TCP系列六》讲了TCP如何解决丢包问题&#xff0c;本文将为大家讲解TCP是如何提高传输效率&#xff0c;减少传输时延的原理。 1. TCP是如何提高传输效率&#xff0c;减少传输时延的 ① 粘包 如果传输的数…

下载数据集用于图像分类并自动分为训练集和测试集方法

一、背景 最近需要用Vision Transformer&#xff08;ViT&#xff09;完成图像分类任务&#xff0c;因此查到了WZMIAOMIAO的GitHub&#xff0c;里面有各种图像处理的方法。而图像处理的前期工作就是获取大量的数据集&#xff0c;用于训练模型参数&#xff0c;以准确识别或分类我…

国标GB28181视频平台EasyGBS国标GB28181软件实现无需插件的视频监控对讲和网页直播

在当今社会&#xff0c;视频监控已经成为公共安全、企业管理、智能城市建设等领域不可或缺的一部分。然而&#xff0c;由于不同厂家和平台之间的兼容性问题&#xff0c;视频监控系统的联网和整合面临巨大挑战。为了解决这个问题&#xff0c;国家制定了《公共安全视频监控联网系…

LabVIEW非接触式模态参数识别系统开发

基于LabVIEW的模态参数识别系统采用非接触式声学方法&#xff0c;结合LabVIEW软件和高精度硬件&#xff0c;实现机械结构模态参数的快速准确识别。降低了模态分析技术门槛&#xff0c;提高测试效率和准确性。 项目背景与意义: 传统的模态分析方法&#xff0c;如锤击法&#x…

一个简单的图像分类项目(六)编写脚本:初步训练

训练的脚本 &#xff0c;用于训练和测试。lib.train.py: import timefrom load_imags import train_loader, train_num from nets import *def main():# 定义网络print(Please choose a network:)print(1. ResNet18)print(2. VGG)# 选择网络while True:net_choose input()if…

【C++】How the C++ Compiler Works

Firstly it needs to pre-process our code which means that any pre-processor statements get evaluated and once our code has been pre-processed we move on to more or less tokenizing(记号化) and parsing(解析) and basically sorting out(整理) this English C lan…

第2次CCF CSP认证真题解

1、相邻数对 题目链接&#xff1a;https://sim.csp.thusaac.com/contest/2/problem/0 本题和第1次认证的第1题“相反数”差不多&#xff0c;都是考察循环遍历比较和计数。 100分代码&#xff1a; #include <iostream> using namespace std; int main(int argc, char …

一款强大的开源OCR工具,支持90+语言识别

大家好&#xff0c;今天给大家分享一款功能强大的开源光学字符识别&#xff08;OCR&#xff09;工具Surya OCR&#xff0c;它基于先进的深度学习技术&#xff0c;提供了高效的字符识别能力&#xff0c;并支持多种语言的文本检测与识别。 项目介绍 核心功能 1.多语言支持 Sur…

破局:DLinear

1. Introduction (1) time series forecasting (TSF)&#xff1b; (2) 回顾 “ Transformer (Vaswani et al. 2017) ” 的各领域优秀表现&#xff1a; (3) IMS vs. DMS : → Consequently, IMS forecasting is preferable when there is a highly-accurate single-step fore…

量化交易打怪升级全攻略

上钟&#xff01; 继续分享量化干货~ 这次要唠的是Stat Arb的新作《Quant Roadmap》(中译名《量化交易路线图》)&#xff0c;为了方便&#xff0c;下文就称呼作者为“老S”&#xff0c;根据公开资料显示&#xff0c;他可是正儿八经的的量化研究员出身&#xff0c;在漂亮国头部对…

【electron8】electron实现“图片”的另存为

注&#xff1a;该列出的代码&#xff0c;都在文章内示例出 1. 另存为按钮事件&#xff1a; const saveAsHandler async () > {const { path, sessionId } recordInfoif(typeof message ! string) return;// 因为我的图片是加密的&#xff0c;所以我需要根据接口返回的路…

全国智能手机使用数据集-dta格式(包含2015、2017、2019三个版本)

数据简介&#xff1a;为推动经济社会高质量发展&#xff0c;缓解经济下行压力&#xff0c;中国加大推动5G基建、大数据中心等科技领域基础设施的建设和完善。数字技术深入各行各业&#xff0c;催生了新业态、新模式、新机会和新就业形式。智能手机作为劳动者使用数字技术的重要…

二叉树的存储方式和遍历方式

文章目录 二叉树的存储方式二叉树的遍历方式DFS--递归遍历DFS--迭代遍历BFS--层次遍历 LC102 二叉树的存储方式 链式存储&#xff08;指针&#xff09;或 顺序存储&#xff08;数组&#xff09; (1)链式存储&#xff1a;通过指针把分布在各个地址的节点串联一起。 (2)顺序存储…

docker上传离线镜像包到Artifactory

docker上传离线镜像包到Artifactory 原创 大阳 北京晓数神州科技有限公司 2024年10月25日 17:33 北京 随着docker官方源的封禁&#xff0c;最近国内资源也出现无法拉取的问题&#xff0c;Artifactory在生产环境中&#xff0c;很少挂外网代理去官方源拉取&#xff0c;小编提供…

大模型面试-Layer normalization篇

1. Layer Norm 的计算公式写一下&#xff1f; 2. RMS Norm 的计算公式写一下&#xff1f; 3. RMS Norm 相比于 Layer Norm 有什么特点&#xff1f; 4. Deep Norm 思路&#xff1f; 5. 写一下 Deep Norm 代码实现&#xff1f; 6.Deep Norm 有什么优点&#xff1f; 7.LN 在 LLMs …

每日一题之电话号码的字母组合

给定一个仅包含数字 2-9 的字符串&#xff0c;返回所有它能表示的字母组合。答案可以按 任意顺序 返回。 给出数字到字母的映射如下&#xff08;与电话按键相同&#xff09;。注意 1 不对应任何字母。 示例 1&#xff1a; 输入&#xff1a;digits "23" 输出&#…

微信小程序学习实录11:精通表单数据绑定,构建高效用户界面

微信小程序中的表单数据绑定是一种非常实用的功能&#xff0c;它允许开发者将页面上的表单元素与数据进行关联&#xff0c;从而实现数据的双向绑定。这样做的好处是能够简化代码&#xff0c;提高开发效率&#xff0c;并且让数据管理变得更加直观。 一、基本概念 数据绑定&am…

Spring Cloud +UniApp智慧工地源码,智慧工地综合解决方案,建筑工程云平台源码

Spring Cloud UniApp智慧工地源码&#xff0c;智慧工地全套源代码包含&#xff1a;PC端大屏端移动端 智慧工地解决方案以工程建设现场管理需求为主线&#xff0c;以AI、物联网、BIM技术为手段&#xff0c;对施工现场进行立体化、全方位、全时段管理&#xff0c;实现规范施工管…