Windows 客户端接入

适用平台:Windows库文件:protect.dll最后更新:2026 年 10 月

本文说明如何在 Windows 项目中集成客户端 SDK。集成后,游戏客户端的网络请求会经由防护节点转发,源站 IP 不再直接暴露在公网。

前置条件

  • 拥有项目源码,开发环境可正常编译发布
  • 具备 C/C++ 基础,能按示例把启动代码加入工程
  • 已在控制台创建 Windows 平台实例,取得接入码
客户端 SDK 安装包含 Windows / Android / iOS 三个平台的库文件
下载 SDK

集成步骤

  1. 解压 SDK 包,找到 windows/x86/protect.dll(32 位)或 windows/x86_64/protect.dll(64 位),按项目位数选择。
  2. 把 protect.dll 复制到项目中,确保与 exe 主程序在同一目录。
  3. 程序启动时加载 DLL,调用 protect_start 启动防护。
  4. 程序退出前调用 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。按本文示例去掉后缀即可。