Launcher 进程入口main
初始化 Qt 应用元数据,创建 LauncherWindow,并在启动参数中识别 p2plauncher:// 深链接。
main.cpp · L7–L29
原型int main(int argc, char *argv[])
参数
| 参数 | 说明 |
|---|
argc | 命令行参数数量 |
argv | 命令行参数数组 |
执行流程
- 创建 QApplication
- 设置组织、应用名称和版本
- 显示主窗口
- 解析首个深链接参数
- 进入事件循环
工程说明
入口保持轻量,只承担进程级初始化与启动参数转交。
关联接口
LauncherWindow::handleDeepLinkLauncherProtocolHandler::parse
查看完整实现
main.cpp
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QCoreApplication::setOrganizationName("P2PPlatform");
QCoreApplication::setApplicationName("P2P Platform Launcher");
QCoreApplication::setApplicationVersion("1.0.0");
LauncherWindow w;
w.show();
QStringList args = QCoreApplication::arguments();
if (args.size() >= 2) {
QString deepLink = args.at(1);
if (deepLink.startsWith("p2plauncher://")) {
w.handleDeepLink(deepLink);
}
}
return a.exec();
}
原型MainWindow::MainWindow(QWidget *parent) : QWidget(parent)
执行流程
- 应用统一控件样式
- 创建 ClientLogic
- 构建 QStackedWidget
- 初始化登录页与工作台
- 绑定业务信号
- 延迟检查更新
工程说明
ClientLogic 作为 MainWindow 子对象,由 Qt 对象树管理生命周期。
关联接口
MainWindow::bindLogicSignalsMainWindow::setupLoginPageMainWindow::setupDashboardPage
查看完整实现
mainwindow.cpp
MainWindow::MainWindow(QWidget *parent)
: QWidget(parent)
{
resize(430, 720);
setMinimumSize(390, 640);
setWindowTitle(QString("P2P Platform 客户端 v%1").arg(APP_VERSION));
qApp->setStyleSheet(
"QWidget { font-family: 'Microsoft YaHei UI', 'Segoe UI'; color: #111827; }"
"QLineEdit { min-height: 34px; border: 1px solid #d1d5db; border-radius: 8px; padding: 6px 10px; background: white; }"
"QLineEdit:focus { border: 1px solid #2563eb; }"
"QPushButton { min-height: 32px; border-radius: 8px; padding: 6px 12px; border: 1px solid #d1d5db; background: #ffffff; }"
"QPushButton:hover { background: #eff6ff; border-color: #93c5fd; }"
"QPushButton:disabled { color: #9ca3af; background: #f3f4f6; }"
"QTabWidget::pane { border: 1px solid #e5e7eb; border-radius: 10px; background: #ffffff; }"
"QTabBar::tab { padding: 8px 14px; margin: 3px; border-radius: 8px; background: #f3f4f6; }"
"QTabBar::tab:selected { background: #2563eb; color: white; }"
"QListWidget { background: #ffffff; border: 1px solid #e5e7eb; border-radius: 10px; }"
"QListWidget::item:selected { background: #dbeafe; color: #111827; }"
);
logic = new ClientLogic(this);
stackedWidget = new QStackedWidget(this);
QVBoxLayout *mainLayout = new QVBoxLayout(this);
mainLayout->setContentsMargins(0, 0, 0, 0);
mainLayout->addWidget(stackedWidget);
setupLoginPage();
setupDashboardPage();
setupUpdateManager();
stackedWidget->addWidget(loginPage);
stackedWidget->addWidget(dashboardPage);
stackedWidget->setCurrentIndex(0);
bindLogicSignals();
QTimer::singleShot(2000, this, [=]() {
if (updateManager) {
updateManager->checkUpdate(false);
}
});
}
原型ClientLogic::ClientLogic(QObject *parent) : QObject(parent)
调用时机
MainWindow 初始化客户端业务层时调用。
执行流程
- 创建 NetworkManager
- 创建 DraftManager
- 连接网络响应信号
- 连接运行日志信号
工程说明
该对象承担 UI 与网络协议之间的稳定边界。
关联接口
ClientLogic::handleNetworkResponseNetworkManager::sendJsonToServer
查看完整实现
clientlogic.cpp
ClientLogic::ClientLogic(QObject *parent) : QObject(parent)
{
netManager = new NetworkManager(this);
draftManager = new DraftManager(this);
connect(netManager, &NetworkManager::sigJsonReceived,
this, &ClientLogic::handleNetworkResponse);
connect(netManager, &NetworkManager::sigLogMessage,
this,
[this](const QString& msg) {
emitUiLog(msg);
});
connect(netManager, &NetworkManager::sigPunchSuccess,
this, &ClientLogic::sigPunchSuccess);
m_heartbeatTimer = new QTimer(this);
m_heartbeatTimer->setInterval(m_heartbeatIntervalMs);
connect(m_heartbeatTimer, &QTimer::timeout,
this, &ClientLogic::sendHeartbeat);
}
原型NetworkServer::NetworkServer(int port, int thread_count) : pool(thread_count, 4096, "business-pool")
参数
| 参数 | 说明 |
|---|
port | UDP 业务端口 |
thread_count | 业务工作线程数量 |
执行流程
- 初始化线程池
- 创建 UDP socket
- 建立 epoll
- 创建 BusinessHandler
工程说明
网络接收与业务执行分离,避免耗时业务阻塞收包。
关联接口
NetworkServer::initUdpServerNetworkServer::startBusinessHandler::dispatchTask
查看完整实现
network_server.cpp
NetworkServer::NetworkServer(int port, int thread_count)
: pool(thread_count, 4096, "business-pool")
{
handler = new BusinessHandler(this);
if (!initUdpServer(port)) {
std::cerr << "❌ [UDP 服务器] 初始化失败。\n";
}
}
原型LauncherWindow::LauncherWindow(QWidget *parent) : QMainWindow(parent)
执行流程
- 创建网络管理对象
- 初始化 UI
- 拉取版本与组件清单
工程说明
启动器与主客户端独立发布,减少通信主程序的组件耦合。
关联接口
LauncherWindow::fetchManifestsLauncherWindow::handleDeepLink
查看完整实现
launcherwindow.cpp
LauncherWindow::LauncherWindow(QWidget *parent)
: QMainWindow(parent)
{
m_net = new QNetworkAccessManager(this);
gameNetManager = new QNetworkAccessManager(this);
setupUi();
fetchManifests();
}
原型LauncherProtocolHandler::parse(const QString& url)
调用时机
主客户端或操作系统拉起 Launcher 后调用。
返回说明
返回 ParsedLink;无法识别时类型保持 Unknown。
执行流程
- 校验 URL scheme
- 提取 query 参数
- 识别 game/custom_game 路径
- 补齐兼容字段
- 返回结构化链接
工程说明
所有深链接参数在进入具体业务前先转为结构化对象。
关联接口
LauncherProtocolHandler::isValidGameJoinLauncherProtocolHandler::isValidCustomGameJoinLauncherWindow::handleDeepLink
查看完整实现
launcherprotocolhandler.cpp
LauncherProtocolHandler::parse(const QString& url)
{
ParsedLink link;
link.originalUrl = url;
QUrl qurl(url);
if (!qurl.isValid() || qurl.scheme() != "p2plauncher") {
return link;
}
QString host = qurl.host();
QString path = qurl.path();
QUrlQuery query(qurl);
link.gameId = query.queryItemValue("game_id");
link.gameName = query.queryItemValue("game_name");
link.roomId = query.queryItemValue("room_id");
link.groupId = query.queryItemValue("group_id");
link.userId = query.queryItemValue("user_id");
link.token = query.queryItemValue("token");
link.serverIp = query.queryItemValue("server");
link.host = query.queryItemValue("host");
link.port = query.queryItemValue("port").toInt();
link.containerPort = query.queryItemValue("container_port").toInt();
link.lobbyPort = query.queryItemValue("lobby_port").toInt();
link.inviteType = query.queryItemValue("invite_type");
link.hostUserId = query.queryItemValue("host_user_id");
link.hostDisplayName = query.queryItemValue("host_display_name");
link.importFile = query.queryItemValue("file");
if (host == "game" && path == "/join") {
link.type = LinkType::GameJoin;
return link;
}
if (host == "custom_game" && path == "/import_config") {
link.type = LinkType::CustomGameImportConfig;
return link;
}
if (host == "custom_game" && path == "/join") {
link.type = LinkType::CustomGameJoin;
if (link.gameId.isEmpty()) {
link.gameId = "custom_game";
}
if (link.gameName.isEmpty()) {
link.gameName = "自定义游戏";
}
if (link.inviteType.isEmpty()) {
link.inviteType = link.groupId.isEmpty() ? "friend" : "group";
}
if (link.lobbyPort <= 0 && link.port > 0) {
link.lobbyPort = link.port + 100;
}
return link;
}
return link;
}