StoneCDN

游戏盾sdk集成指南(原生库2025版)

14 1 月, 2025 stonecdn

集成前准备

开始集成前建议先对自身业务做下梳理,确认下哪些业务需要接入 SDK,明确对应的 业务端口、域名以及业务服务器 IP(注意:业务服务器 IP 必须未在公网上解析暴露过,无法通过解析获取,最好是能跟其 他的业务隔离开)。

创建SDK接入实例,创建成功会得到AppID 跟 AppKey

转发规则配置

每条转发规则需要确认转发key(唯一表示一个转发规则),源服务器的IP/域名,端口,通信协议(tcp/udp)

接入流程

调用以下几个必须的接口即可。

  • 调用 Init 接口初始化,传入参数 AppID、AppKey(两个参数必填,必须调用)。 客户端启动后尽快初始化,且初始化一次就好(app 切后台再切回需重新调用)。
  • 调用 GetTCPServerAddr 接口获取本地 TCP 代理 IP 以及端口(TCP 转发必须调用)。
  • 调用接口 GetClientIP 获取客户端真实 IP(根据业务选择是否调用,非必须)。
  • 通过 HTTP 协议中请求头 X-Forward-For 或者 TCP 中封装到业务数据回源。
  • 和本地代理建立链接,发送请求。

集成注意事项

  • 安卓、IOS、PC 端,不论 http、tcp、websocket 每次发起请求、断线重连以及 ios 在锁屏恢恢复程序 都要重新调用 GetTCPServerAddr,不可以缓存之前的返回结果。因为系统可能会关闭本地代理端口,没有重新调用接口直接建联将 建联失败,导致业务异常。
  • Android 提供armeabi-v7a,x86, x86_64,arm64-v8版的动态库,可以兼容所有安卓设备,有其 他第三方 SDK需要保持库文件一致,否则可能会导致程序崩溃。
  • 若需要封禁模拟器,请联系技术
  • ios 我们提供了.a 文件,集成即可(iphone5之前的设备不再支持)。
  • 客户端的网络处理需更健壮,比如超时处理,断线重连。
  • SDK节点较多且会不定期变动,建议关闭源安全策略。

各平台接入示例

以下示例介绍接入SDK必须的接口,完整调用可以看完整代码示例

  • Android

运行环境:Android 4.1 及以上系统版本 将 Android SDK引入到工程中

代码示例

import com.xshield.jni.ShieldService;boolean succeed = ShieldService.Init("$AppID", " $AppKey "); // 若初始化成功则返回 true
String addr = ShieldService.GetTcpProxyAddr(“test.com”);
connect(addr);

通过上一步中的 IP 和端口建立连接,发送接收业务数据(建议放在初始化完成后执行,以免卡住UI线程)
获取安全代理的IP和端口以免卡住UI线程
初始化 SDK(将获取到的 AppID 跟 AppKey 传入接口)

  • IOS

运行环境:iOS 8.0 及以上系统版本,将 IOS SDK加到应用工程。

使用 XCode 打开应用工程,将 libxshield.a 添加到工程中。

代码示例

XShieldIOS *sdk = [[XShieldIOS alloc] init];
[sdk init: @"$AppID " appKey: @" $AppKey "]; // 初始化成功返回 true
#include "xshield-ios.h"
NSString* addr = [sdk getTCPAddr:@”test.com”];
connect(addr);

通过上一步中的 IP 和端口建立连接,发送接收业务数据
获取安全代理的 IP 和端口(这里以对接配置为 TCP 转发为例)
初始化 SDK (将获取到的AppID跟AppKey传入接口)

集成验收

客户端抓包分析,源 IP 是否暴露。(需要一个可共享热点网络的电脑,安装抓包软件, 如 wireshark)。将 PC 的热点共享出来(wifi热点软件或者系统自带热点功能),手机连 热点网络,打开抓包软件,再开启软件,将所有业务测试几遍,看是否能过抓到业务源 IP。 复核有无其他域名解析到源 IP 的情况,如有建议业务隔离
获取真实 IP,业务上确认下是否正常获取到用户真实 IP,获取失败可能得到的是高防节点 IP,可提供 IP 同技术确认
业务上线前测试,建议上线前多做测试,可灰度测试 2~3 天,再进行全局更新。

SDK集成常见问题解答

1.解决端口冲突

经过多年的观察及统计,端口冲突问题只是在个别客户端设备上发生且发生概率及低。 但为彻底解决这个问题,我们还是建议您采用我们提供的高级功函数能将这个问题彻底解决掉。

由于我们的sdk 是根据您配置的“转发规则”在客户端设备上开相应的端口,这就有极低的概率在个别的客户端发生端口冲突。

端口冲突有两类情形:

  • 第一种情形:您配置的 某个端口在个别客户端上已被其它应用占用了,则该用户不能正常使用您的应用;
  • 第二种情形:您有多个应用但使用同一个实例,而且用户在同一个设备上有时又会同时打开您的 多个应用;用户打开的第一个应用时已把您实例的所有端口都占用了,第二个应用打开时 就无法打开这些端口了。

这个问题在 PC上没关系,第二个打开的应用业务是正常的,因为第二个应用会通过第一个应用连接到 sdk,但在移动端就会有问题,第二个应用在一开始时还是正常的,因为这时第二个应用会通过第一个应用连接到 sdk,在用户使用第二个应用时第一个应用会被切到后台,过段时间第一个应用可能会被系统休眠,这时第二个应用就无法连接了。

解决这个问集成起来也是很简单的,代码过程如下

dunSetAutoChangePort(1);//设置成自动更换冲突端口,只需要调用一次

int ret = clinkStart(key);//启动盾,有些系统用 start 具体请看另一个文档,只需要调用一次

//在需要新建连接时调用下面这行代码来获取新端口

int new_tcpPort = dunGetCurrentTCPPort("127.0.10.21", 600);//获取新的tcp对应的端口

//接下来采用new_tcpPort来连接应用​

//connect("127.0.10.21", new_tcpPort) 例如这行伪代码

再举个例子,例如转发规则里配置的是 127.0.10.21:600 转到 101.21.31.5:600,未集成盾前和集成盾后并解决端口冲突的对比伪代码

未集成盾前的连接 connect("101.21.31.5",600) 

集成盾后的连接 connect("127.0.10.21", dunGetCurrentTCPPort("127.0.10.21",600))

1.1 设置是否自动更换冲突的端口

本函数必须在调用盾start前调用才有效

函数原型:void dunSetAutoChangePort(int val)

  • 参数:val:是否自动更换。0:不自动更换、1:当该端口冲突时自动更换成新端口
  • 功能:当 val 设为 1,在盾启动时如果检测到某个端口已被占用或其它原因法无打开 这个这端口时,就会自动生成一个随机可用的端口,并把这个随机生成的端口和原来的端 口进行关联,您的程序在新建连接时就可以通过 sdk 提供的 dunGetCurrentTCPPort 或 dunGetCurrentUDPPort 函数来获取新生成的端口,采用新的端口来进行连接,这样就解决了端口冲突问题。

下面是各系统下对应的 sdk 函数定义,具体调用示例可查看“demo 高级功能”里的项目

Windows: 
extern "C" CLINKAPI_API void dunSetAutoChangePort(int val);

android: 
类:cn.ay.clinkapi.Api

public native void dunSetAutoChangePort(int val);

IOS 静态库: 
 类:ClinkAPI
void dunSetAutoChangePort(int val);

IOS 动态库: 
 extern "C" void dunSetAutoChangePort(int val);

Unity 
类:ClinkSDKForUnity 
 public static void dunSetAutoChangePort(int val)

Uni-app 
插件name:ayClinkApiForUni
插件函数:dunSetAutoChangePort(val)
​

1.2获取当前tcp对应端口

在新建 tcp 连接前您要调用这个函数来获取您将要连接的端口对应的新端口,因为您原来的端口可能存在端口冲突,sdk 已将该端口换成另一个端口。

  • 函数原型:int dunGetCurrentTCPPort(const char* ip, int port)
  • 参数:ip:转发规则中的客户连接 IP,也就是 127 开头的 IP port:转发规则中的客户连接端口,也就是 127 开头 IP 的对应端口
  • 返回:获取到的新端口,如果传入的端口没有冲突或转发规则不存在返回的将和传 入的端口一样,如果有冲突返回的是改变后的新端口。

下面是各系统下对应的 sdk 函数定义,具体调用示例可查看“demo 高级功能”里的项目:

Windows:
extern "C" CLINKAPI_API int dunGetCurrentTCPPort(const char* ip, int port);

android:
类:cn.ay.clinkapi.Api
public native int dunGetCurrentTCPPort(String ip,int port);

IOS 静态库:
类:ClinkAPI
int dunGetCurrentTCPPort(const char* ip, int port);

IOS 动态库:
extern "C" void dunGetCurrentTCPPort(int val);

Unity
类:ClinkSDKForUnity
public static int dunGetCurrentTCPPort(string ip, int port)

Uni-app
插件name:ayClinkApiForUni
插件函数:dunGetCurrentTCPPort(ip,port)

1.3 获取当前udp对应端口

在新建 udp 连接前您要调用这个函数来获取您将要连接的端口对应的新端口,因为您 原来的端口可能存在端口冲突,sdk 已将该端口换成另一个端口。

  • 函数原型:int dunGetCurrentUDPPort(const char* ip, int port)
  • 参数:ip:转发规则中的客户连接 IP,也就是 127 开头的 IP port:转发规则中的客户连接端口,也就是 127 开头 IP 的对应端口
  • 返回:获取到的新端口,如果传入的端口没有冲突或转发规则不存在返回的将和传入的端口一样,如果有冲突返回的是改变后的新端口。

下面是各系统下对应的 sdk 函数定义,具体调用示例可查看“demo 高级功能”里的项目:

Windows: 
extern "C" CLINKAPI_API int dunGetCurrentUDPPort(const char* ip, int port);

android: 
类:cn.ay.clinkapi.Api
public native int dunGetCurrentUDPPort(String ip,int port);

IOS 静态库: 
 类:ClinkAPI
int dunGetCurrentUDPPort(const char* ip, int port);

IOS 动态库: 
 extern "C" void dunGetCurrentUDPPort(int val);

Unity 
类:ClinkSDKForUnity 
 public static int dunGetCurrentUDPPort(string ip, int port)

Uni-app 
插件name:ayClinkApiForUni
插件函数:dunGetCurrentUDPPort(ip,port)
​​

2.其它功能函数

2.1获取客户端IP

用来在客户端获取该客户端当前的 IP。转发规则中“获取 IP 方式”无论设成什么, 这个接口都是有效的,这个是在客户端获取的,转发规则是给您的服务器端获取的,两个没有关系,只是获取到的客户端 IP 都是一样的。

例如:您可以在用户登录时,把登录信息和客户端 IP 一起发送到登录服务器,这样如果你后端服务器存在多次转发的话也可获取到客户的真实 IP。

  • 函数原型:long long dunGetClientIP()
  • 返回:有符号 64 位小字头整数 IP 值,通过其它函数可转成字符串格式的 IP,返回 0 说明盾未启动或未启动成功 将整数 IP 转成字符串格式 IP 算法代码如下
string ipstr = ip / 256 / 256 / 256 % 256 + "." + ip / 256 / 256 % 256 + "." + ip / 256 % 256 + "." + ip % 256;

下面是各系统下对应的 sdk 函数定义,具体调用示例可查看“demo 高级功能”里的项目:

Windows:
extern "C" CLINKAPI_API long long dunGetClientIP();

android:
类:cn.ay.clinkapi.Api
public native long dunGetClientIP();

IOS 静态库:
类:ClinkAPI
long long dunGetClientIP();

IOS 动态库:
extern "C" long long dunGetClientIP();

Unity
类:ClinkSDKForUnity
public static long dunGetClientIP()

Uni-app
插件name:ayClinkApiForUni
插件函数:dunGetClientIP()

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注