proxy_client
简介
做为客户端接入proxy server
- 一般是玩家客户端(大部分情况下为非gs实现)才需要接入proxy server;
这个pkg主要是client gs使用,用来实现一些测试功能以及演示如何接入proxy server;
组件接口
CommonConnection.gs
公共服务器代理连接对象(用于pkg.request_client)
函数原型 | 函数作用 |
---|---|
void FProxyConnection.process_command(mixed payload) | 虚函数 - 公共服务器消息的处理函数 |
FProxyConnection.gs
代理连接对象的基础组件,所有的代理连接对象都应该继承本组件
函数原型 | 函数作用 |
---|---|
object get_proxy_client_ob() | 获取本连接关联的代理客户端对象 |
string get_name() | 获取本连接名称 |
void on_message(string msg, function func) | 设置消息处理函数 |
object bind_dispatcher(mixed co) | 绑定消息处理协程对象 |
bool is_connected() | 连接是否已建立 |
void send(string cmd, ...) | 虚函数 - 向目标服务器发送消息 |
mixed send_request(string cmd, ...) | 虚函数 - 向目标服务器发送消息并等待消息处理结果 |
ProxyClient.gs
接入proxy server的客户端连接对象
ProxyClient对象在创建时可以指定对象的所有者owner;owner对象将处理ProxyClient对象收到的消息(调用owner的perform_recv_in_co方法);
当owner对象未指定时(为nil),ProxyClient对象收到的消息将直接丢弃;
函数原型 | 函数作用 |
---|---|
void add_connection(string name, object connection) | 添加一个代理连接 |
object remove_connection(string name) | 移除一个代理连接 |
object get_connection(string name) | 根据连接名称获取代理连接对象 |
void set_connection_factory(string type, function func) | 设置指定类型的代理连接对象的创建函数 |
object new_connection(ProxyConnectionProperties properties) | 通过指定参数新建一个代理连接对象 |
void close_connection(string name) | 关闭指定名称的代理连接 |
bool connect(string host, int port, map para = , bool using_websocket = false) | 连接代理服务器 |
void send(string cmd, ...) | 向代理服务器发送消息 |
mixed send_request(string cmd, map args, int timeout = 30) | 向代理服务器发送消息并等待消息处理结果 |
void disconnect() | 主动断开和代理服务器的连接 |
void on_message(string msg, function func) | 响应指定名称的网络消息 |
void invoke_message(string msg, ...) | 执行消息处理函数 |
proxy_client.gs
函数原型 | 函数作用 |
---|---|
object create_client(map para = ) | 创建一个到proxy server的客户端连接 |
类
ProxyConnectionProperties
代理连接的属性表
成员变量
变量名 | 类型 | 初始值 | 须初始化 | 描述 |
---|---|---|---|---|
name | string | nil | 可选 | 代理连接名称(ProxyClient实例下唯一) |
type | string | nil | 可选 | 连接类型(代理服务器允许的连接类型) |
host | string | nil | 可选 | 目标服务器地址 |
port | int | 0 | 可选 | 目标服务器端口 |
connect_para | map | nil | 可选 | 目标服务器的额外连接参数 |
成员方法
函数原型 | 函数作用 |
---|---|
map get_properties() | 获取代理连接的属性 |
样例
import pkg.boot;
import pkg.proxy_client;
import pkg.proxy_client.GameConnection;
import pkg.proxy_client.CommonConnection;
import gs.lang.*;
import gs.bin.*;
import pkg.auth_client;
import pkg.social_client;
// 代理服务器ip/port
const string PROXY_HOST = "127.0.0.1";
const int PROXY_PORT = 18000;
// 认证服务器连接信息
const map AUTH_SERVER = {
"name" : "auth1",
"type" : "auth_server",
"host" : "127.0.0.1",
"port" : 5200
};
// 游戏服务器连接信息
const map GAME_SERVER = {
"name" : "game1",
"type" : "game_server",
"host" : "127.0.0.1",
"port" : 5002
};
// 社交服务器连接信息
const map SOCIAL_SERVER = {
"name" : "social1",
"type" : "social_server",
"host" : "127.0.0.1",
"port" : 8432
};
// 测试账号/密码
readonly string ACCOUNT := "test_account";
readonly string PASSWORD := md5("test_password").to_hex().to_upper();
// 设置启动选项
BootOption boot_option = boot.new_option();
boot_option.apply();
// 执行测试
// 连接server1测试
public void test()
{
object proxy_client_ob = proxy_client.create_client();
// 连接代理服务器
map para = {
// 连接参数
};
if (! proxy_client_ob.connect(PROXY_HOST, PROXY_PORT, para))
return;
if (! assure_account(proxy_client_ob))
{
printlnf("登录失败: 账号不存在");
return;
}
mixed token_info = take_token(proxy_client_ob);
if (! token_info)
{
printlnf("登录失败:从验证服务器获取TOKEN失败");
return;
}
printlnf("开始认证");
if (! login(proxy_client_ob, token_info))
{
printlnf("登录失败");
return;
}
printlnf("认证成功");
}
// 如果账号不存在就创建
bool assure_account(object proxy_client_ob)
{
map client_para = {
"host" : AUTH_SERVER.host,
"port" : AUTH_SERVER.port,
"connect_func" : (: callback_new_auth_server_connection, proxy_client_ob :)
};
object auth_ob = auth_client.create_client(client_para);
defer auth_ob.close();
// 检查账号是不是存在
map para = {
"account" : ACCOUNT,
};
mixed result = auth_ob.send_request("client_check_account", para);
if (result && result["exists"])
return true;
// 创建账号
map create_para = {
"type" : "normal", // 普通账号
"account" : ACCOUNT,
"password" : PASSWORD,
};
mixed create_result = auth_ob.send_request("client_create_account", create_para);
if (! create_result || create_result["error"])
{
printlnf("创建账号%s失败: %M", ACCOUNT, create_result);
return false;
}
return true;
}
// 获取登录令牌
mixed take_token(object proxy_client_ob)
{
map client_para = {
"host" : AUTH_SERVER.host,
"port" : AUTH_SERVER.port,
"connect_func" : (: callback_new_auth_server_connection, proxy_client_ob :)
};
object auth_ob = auth_client.create_client(client_para);
defer auth_ob.close();
map para = {
"account" : ACCOUNT,
"password" : PASSWORD,
};
mixed token_info = auth_ob.send_request("client_auth_account", para);
if (! token_info || token_info["error"])
{
printlnf("从验证 服务器验证账号密码获取token失败:%M", token_info);
return nil;
}
return token_info;
}
bool login(object proxy_client_ob, map token_info)
{
// 创建游戏服务的代理连接对象
ProxyConnectionProperties properties = ProxyConnectionProperties.new_by_map(GAME_SERVER);
object game_connection = proxy_client_ob.new_connection(properties);
if (! game_connection)
return false;
map para = {
"token" : token_info["token"],
"account" : token_info["account"],
"account_id" : token_info["account_id"]
};
let bool auth_success, mixed gs_token = game_connection.send_request("auth", ACCOUNT, nil, para);
if (! auth_success)
{
printlnf("兑换游戏服务器token超时");
return false;
}
// 响应游戏服务器消息
game_connection.on_message("social_account", (: on_social_account :));
map login_dict = {
"account" : token_info["account"],
"account_id" : token_info["account_id"],
"version" : "0.1.0.0",
"device_uid" : "0000",
"token" : gs_token
};
let bool login_success, mixed login_result = game_connection.send_request("login", login_dict);
if (! login_success)
{
printlnf("登录失败: %M", login_result);
return false;
}
return true;
}
// 游戏服务器: 响应"social_account"消息
void on_social_account(object game_connection, string rid, map social_token)
{
// 查询服务器信息
mixed server_info = game_connection.send_request("query_server_info");
if (! server_info)
return;
string server_id = server_info["server_id"];
map client_para = {
"host" : SOCIAL_SERVER.host,
"port" : SOCIAL_SERVER.port,
"account" : rid,
"server_id" : server_id,
"auth_account_para" : {
"token" : social_token["token"]
},
// proxy_connection_func
"connect_func" : (: callback_new_social_server_connection, game_connection.get_proxy_client_ob() :)
};
object client_ob = social_client.create_client(client_para);
client_ob.ping();
}
// 回调函数,提供创建验证服代理连接对象(pkg.auth_client)
object callback_new_auth_server_connection(object proxy_client_ob, string host, int port, map connect_para, bool using_websocket)
{
ProxyConnectionProperties properties = ProxyConnectionProperties.new();
properties.host = host;
properties.port = port;
properties.connect_para = connect_para;
properties.name = AUTH_SERVER.name;
properties.type = AUTH_SERVER.type;
object connection = proxy_client_ob.new_connection(properties);
if (! connection)
return nil;
return connection;
}
// 回调函数,提供创建社交服代理连接对象(pkg.social_client)
object callback_new_social_server_connection(object proxy_client_ob, string host, int port, map connect_para, bool using_websocket)
{
ProxyConnectionProperties properties = ProxyConnectionProperties.new();
properties.host = host;
properties.port = port;
properties.connect_para = connect_para;
properties.name = SOCIAL_SERVER.name;
properties.type = SOCIAL_SERVER.type;
object connection = proxy_client_ob.new_connection(properties);
if (! connection)
return nil;
return connection;
}