Windows 客户端接入
本文说明如何在 Windows 项目中集成客户端 SDK。集成后,游戏客户端的网络请求会经由防护节点转发,源站 IP 不再直接暴露在公网。
前置条件
- 拥有项目源码,开发环境可正常编译发布
- 具备 C/C++ 基础,能按示例把启动代码加入工程
- 已在控制台创建 Windows 平台实例,取得接入码
客户端 SDK 安装包含 Windows / Android / iOS 三个平台的库文件
下载 SDK
集成步骤
- 解压 SDK 包,找到
windows/x86/protect.dll(32 位)或windows/x86_64/protect.dll(64 位),按项目位数选择。 - 把
protect.dll复制到项目中,确保与 exe 主程序在同一目录。 - 程序启动时加载 DLL,调用
protect_start启动防护。 - 程序退出前调用
protect_stop,再卸载 DLL。
退出前必须调用停止函数。完整时序是:加载 DLL → 启动 → 正常运行 → 停止 → 卸载。跳过停止直接结束进程,可能造成进程死锁。
启动参数
启动函数只有一个参数 config,类型为 C 字符串,内容是一段 JSON,通常只有一个字段:
{"access_key":"接入码"}
在 C/C++ 中注意引号要转义:
const char* config = "{\"access_key\":\"接入码\"}";
DWORD result = protect_start(config);
完整示例(C++)
先声明函数指针类型并定义全局句柄:
#include <windows.h>
#include <iostream>
// 定义函数指针类型
typedef DWORD (WINAPI *protect_start_t)(const char* config);
typedef DWORD (WINAPI *protect_stop_t)();
// 全局变量保存 DLL 句柄与函数指针
HINSTANCE hDLL = NULL;
protect_start_t protect_start = NULL;
protect_stop_t protect_stop = NULL;
加载 DLL 并获取函数地址:
bool LoadMyDLL()
{
hDLL = LoadLibrary("protect.dll");
if (hDLL == NULL) {
std::cerr << "无法加载 DLL" << std::endl;
return false;
}
protect_start = (protect_start_t)GetProcAddress(hDLL, "protect_start");
if (protect_start == NULL) {
std::cerr << "无法加载函数地址: protect_start" << std::endl;
FreeLibrary(hDLL);
return false;
}
protect_stop = (protect_stop_t)GetProcAddress(hDLL, "protect_stop");
if (protect_stop == NULL) {
std::cerr << "无法加载函数地址: protect_stop" << std::endl;
FreeLibrary(hDLL);
return false;
}
return true;
}
释放 DLL:
void UnloadMyDLL()
{
if (hDLL != NULL) {
protect_stop = NULL;
protect_start = NULL;
FreeLibrary(hDLL);
hDLL = NULL;
}
}
用 main 函数演示完整生命周期:
int main()
{
// 加载 DLL
if (!LoadMyDLL())
return -1;
// 调用启动函数
const char* config = "{\"access_key\":\"接入码\"}";
DWORD result = protect_start(config);
std::cout << "函数返回: " << result << std::endl;
// 正常运行,这里用等待 30 秒替代
Sleep(30000);
// 调用停止函数
protect_stop();
// 释放 DLL
UnloadMyDLL();
return 0;
}
返回值与错误信息
protect_start 返回 0 表示启动成功,其他值表示失败。
失败原因可以通过 protect_error 获取。它返回最近一次错误的描述(UTF-8 字符串),无错误时返回空串:
typedef const char* (*protect_error_t)(void);
protect_error_t protect_error =
(protect_error_t)GetProcAddress(hDLL, "protect_error");
if (result != 0 && protect_error != NULL) {
std::cout << "启动失败: " << protect_error() << std::endl;
}
返回的指针在下次调用
protect_start / protect_stop / protect_error 之前有效。需要长期保存时,请立即拷贝到自己的缓冲区。
接入码区分平台。控制台创建实例时必须选择 Windows 平台,否则启动会失败。如果同时支持 32 位与 64 位客户端,需要分别放置对应位数的 DLL。
常见问题
启动返回非 0
- 检查接入码是否与实例一致、是否属于 Windows 平台
- 检查
protect.dll是否与 exe 同目录,位数是否匹配 - 确认实例未被暂停或到期
进程退出时卡住
通常是漏掉了 protect_stop。确认所有退出路径(包括异常分支)都会走到停止函数。
GetProcAddress 返回 NULL
DLL 导出的函数名是未修饰的 protect_start / protect_stop / protect_error,不带 @4、@0 这类后缀。
网上流传的部分示例代码写的是 GetProcAddress(hDLL, "protect_start@4"),那是早期版本 DLL 暴露 __stdcall 修饰名时的写法,对当前版本会直接返回 NULL。按本文示例去掉后缀即可。