libgsc(Game Server Communication Library)(三)
来源:互联网 发布:centos 安装无线网卡 编辑:程序博客网 时间:2024/05/16 15:09
libgsc的编程方式.
以Db.cpp为例进行说明, 主要是分为三个部分.
1. 业务处理转移表的定义.
转义表中定义了当前actor对自己关注的每个业务的处理函数指针, 为了配置的方便, 命令字被省略, 也就是命令字应该从0x00开始, 可在Db.h
中找到它们的定义.
enum ItcDb{ITC_DB_INIT = 0x00, //ITC_DB_INSERT_SOMETHING,ITC_DB_UPDATE_SOMETHING,ITC_DB_QUERY_SOMETHING,ITC_DB_DELETE_SOMETHING,};转移表中的CAST_ITC_CB来自于libgsc中的Gsc.h, 以适应不同的pb消息参数, 注ITC(inter-thread communication)
#define CAST_ITC_CB(___X___) (ushort (*)(Actor* actor, Trans* trans, Msg* msg, Message* oper))(___X___)
2. actor的handle虚函数实现.
handle函数有三个参数, 第一个trans, 当前正在进行的事务, 由发送者开启, 第二个msg, 它携带了发送者/接收者等可能会在业务处理中用
到的信息. 第三个oper, 是msg的消息正文, 这是一个pb消息基类, 是实际的业务内容, 它可以为空, 也就是说, 仅仅使有命令字就可以表达想
要的目的了, handle的实现大同小异, 最终都是根据命令字把worker线程传递的业务消息转移到真正的处理函数中去.
ushort Db::handle(Trans* trans, Msg* msg, Message* oper)
3. 业务代码实现.
参数1, db, 表示谁收到了这个消息, 这里是db对象自己, 参数2,3同上, 参数4, 也是上面的oper. 这个消息是通信双方(发送者和接收者)约定好.
不能出错.
ushort Db::itc_db_init(Db* db, Trans* trans, Msg* msg, ItcComm* itc)
不同的处理结果, 可返回不同的返回值, 在与网络无关的事务中, 返回值暂时没有太多意义, 仅表示处理结果, 如果不调用
trans->forward()函数, 事务总是被结束.
顺便在这里解释一下, actor的事务分为三种, 如下:
enum TransType{TRANS_TYPE_ITC = 0x00, /** ITC事务, 仅限于进程内部消息流转. */TRANS_TYPE_NET_NO_ACTOR, /** 网络上与actor无关的事务. */TRANS_TYPE_NET_ACTOR, /** 网络上与actor有关的事务. */};
上面的Db::itc_db_init是第一种, 事务具体属于哪一种, 是在事务最早被创建时指明, 如itc_db_init消息的在发送时的代码:
Gsc::instance()->sendItc(ITC_DB_INIT, Gas::instance(), Db::instance(), NULL /** 无消息正文. */); /** 尝试数据库初始化. */
另外两种事务, 总是在收到消息时开启, 具体可见GscEvent的实现, 需要说明的是, 与网络有关的事务处理函数返回值有几个约定:
1. 处理函数调用了trans->end(), 这时返回值总是GX_RET_SUCCESS, 但事务会结束, end中的message参数会被发送至客户端.
2. 处理函数调用了trans->forward(), 返回值也总是GX_RET_SUCCESS, 事务被前转.
3. 处理函数没有调用end或forward, 事务总是被结束, 但不同的返回值导致不同的行为:
a). return GX_RET_SUCCESS, 什么也不做.
b). return GX_RET_FAILURE, 关闭套接字.
c). return 其它返回值, 发送返回值给客户端.
/* * Db.cpp * * Created on: Aug 6, 2014 5:26:14 PM * Author: xuzewen */#include "Db.h"#include "Aid.h"#include "NetInit.h"#include "TaskMgr.h"Db* Db::ad = new Db(AID_DB, "Db");/** actor消息处理转移表. */static actor_handle_cb __cb__[] = { ///***/CAST_ITC_CB(Db::itc_db_init),/***/CAST_ITC_CB(Db::itc_db_insert_something),/***/CAST_ITC_CB(Db::itc_db_update_something),/***/CAST_ITC_CB(Db::itc_db_query_something),/***/CAST_ITC_CB(Db::itc_db_delete_something),//};Db::Db(ullong aid, const char* name, int wid) :ActorIdpd(aid, name, wid){this->mysql = NULL;}Db* Db::instance(){return Db::ad;}void Db::reset(){}/** actor消息处理入口. */ushort Db::handle(Trans* trans, Msg* msg, Message* oper){if (msg->cmd >= sizeof(__cb__) / sizeof(actor_handle_cb)){LOG_FAULT("it`s an unexplainable cmd: %04X, from: %s\n", msg->cmd, msg->f->name.c_str())return GX_RET_FAILURE;}if (msg->cmd != ITC_DB_INIT) /** 非初始化消息时, 总是先尝试获得连接. */this->getConn();//return __cb__[msg->cmd].handle(this, trans, msg, oper);}void Db::getConn(){while (this->mysql == NULL){this->mysql = MysqlDb::getConn("host", "usr", "pwd", "db", 3306, "UTF-8");if (this->mysql == NULL){Misc::sleep(1000);continue;}break;}}void Db::close(){MysqlDb::close(this->mysql);this->mysql = NULL;}/*----------------------------------------------------------------*//* *//* 消息 *//* *//*----------------------------------------------------------------*//** 数据库初始化. */ushort Db::itc_db_init(Db* db, Trans* trans, Msg* msg, ItcComm* itc){Gsc::instance()->regNetInitActor(NetInit::instance()); /** 注册网络初始消息处理器. */ActorMgr::instance()->addActor(Gas::instance()); /** 添加Gas进程. */ActorAuto::instance()->start(TaskMgr::flush); /** 启动actor驱动器. *///if (1 != 1){db->getConn();if (!db->loadGs() || !db->loadGc()) /** 在这里加载数据库到内存. */exit(1);}return trans->forward(ITC_GAS_INIT, db, Gas::instance(), NULL); /** 加载成功后, 前转给Gas. */}/** 插入. */ushort Db::itc_db_insert_something(Db* db, Trans* trans, Msg* msg, ItcComm* itc){return GX_RET_SUCCESS;}/** 更新. */ushort Db::itc_db_update_something(Db* db, Trans* trans, Msg* msg, ItcComm* itc){return GX_RET_SUCCESS;}/** 查询. */ushort Db::itc_db_query_something(Db* db, Trans* trans, Msg* msg, ItcComm* itc){return GX_RET_SUCCESS;}/** 删除. */ushort Db::itc_db_delete_something(Db* db, Trans* trans, Msg* msg, ItcComm* itc){return GX_RET_SUCCESS;}/** 加载所有的GS. */bool Db::loadGs(){static const char* sql = "SELECT UID, USR, PWD, NAME, SRVHOST, SRVPORT, PRVHOST, PRVPORT, UNIX_TIMESTAMP(GTS) FROM TB_GS ORDER BY UID ASC";MYSQL_RES* rst = MysqlDb::getResult(this->mysql, sql);if (rst == NULL)return false;size_t c = 0;MYSQL_ROW row = NULL;while ((row = mysql_fetch_row(rst)) != NULL){//uint uid = 0x00;//MysqlDb::getIntVal(row[0], (int*) &uid);//Gs* gs = new Gs(AID_GS_S + uid, "Gs", Gsc::instance()->randWid(AID_GS_S + uid));/** 构造一个GS-actor对象, 并挂在某个工作线程下. *///gs->uid = uid;//MysqlDb::getStrVal(row[1], &gs->usr);//MysqlDb::getStrVal(row[2], &gs->pwd);//MysqlDb::getStrVal(row[3], &gs->name);//MysqlDb::getStrVal(row[4], &gs->srvhost);//MysqlDb::getIntVal(row[5], &gs->srvport);//MysqlDb::getStrVal(row[6], &gs->prvhost);//MysqlDb::getIntVal(row[7], &gs->prvport);//MysqlDb::getTimeVal(row[8], &gs->gts);//ActorMgr::instance()->addActor(gs);/** 加入到actor管理器. *///GsMgr::instance()->addGs(gs);++c;}MysqlDb::relResult(rst);LOG_INFO("load TB_GS successfully, size: %lu\n", c)return true;}/** 加载所有的GC. */bool Db::loadGc(){static const char* sql = "SELECT UID, USR, PWD, UNIX_TIMESTAMP(GTS) FROM TB_GC ORDER BY UID ASC";MYSQL_RES* rst = MysqlDb::getResult(this->mysql, sql);if (rst == NULL)return false;MYSQL_ROW row = NULL;while ((row = mysql_fetch_row(rst)) != NULL);MysqlDb::relResult(rst);LOG_INFO("load TB_GC successfully, size: %lu\n", 1L)return true;}Db::~Db(){}
其它.
libgsc的网络报文格式.
typedef struct{uint len; /** 整个报文长度. */uint tid; /** 事务id. */ushort cmd; /** 命令字. */ushort ret; /** 返回值. */uchar* dat; /** 整个报文. */} gsc_pdu; /** GSC通信报文. */例: 00 00 00 16 00 00 00 FF 00 00 00 00 0A 03 6B 65 79 12 03 65 78 74
00 00 00 16, 长度, 即整个pdu为22个字节.
00 00 00 FF, 事务ID, 四字节.
00 00, 命令字, 0x00
00 00, 返回值,
0A 03 6B 65 79 12 03 65 78 74, 消息正文, 序列化后的pb对象.
- libgsc(Game Server Communication Library)(三)
- libgsc(Game Server Communication Library)(二)
- libgsc(Game Server Communication Library)(四)
- libgsc(Game Server Communication Library)(五)
- 一个轻量级Actor并发框架的c++实现, libgsc(Game Server Communication Library)(一)
- inter portlet communication library
- LJ-V7000 Series Communication Library
- Network Game - Network Communication Model 1
- Network Game - Network Communication Model 2
- Network Game - Network Communication Model 3
- Network Game - Network Communication Model 4
- Network Game - Network Communication Model 5
- [书籍]《Programming Flash Communication Server》
- Macromedia Flash Communication Server MX
- Flash Communication Server笔记一
- Flash Communication Server笔记二
- flash communication with java server
- Communication error with Jack server
- 设置静态IP
- 热噶热狗绕过绕过人
- Linux中断(interrupt)子系统之二:arch相关的硬件封装层
- Init进程
- 发违法违法未访问
- libgsc(Game Server Communication Library)(三)
- php常见开发模式
- 分为个人问过违法违法
- 自定义UITableViewCell 中UIButton 的确定事件
- c#判断某个控件是否已经注册某事件
- 关于SVN主干和分支合并问题
- STM32神舟III号 驱动直流电机学习(一)
- 隔热噶热噶绕过绕过
- php------如何求解字符串“中国2北333京”的字符数(一个中文一个字符),并找到第四个字符“北”