plain framework 商业版 开发总结1 updated
每天对着不同的计划,多多少少有一种无形的压力。特别是对技术不好的我来说,过程中遇到的问题实在不少,时常纠结良久。时间慢慢流逝,最后虽然感觉有些不足,但是也不至于差强人意。商业版的PF核心已经升级到1.0.5版本,增添和完善了许多功能。核心主要完善了网络模块、脚本模块、文件模块、引擎模块、缓存模块等等,并制作了基本的场景插件和AI插件。未来的PF将支持更多的功能,将安装和使用更加的自动化,执行一个脚本就能完成许多不必要的步骤。所以未来的脚本工具是一个必须完成的功能,在此我们将迎来一个个热爱开源项目的同仁和期待你们的加入。5月商业版服务器的开发总结,将全面将制作原理和遇到的麻烦分享,希望大家能够一起进步。原理好比是渔网和捕鱼的技术,虽然没有源代码,我想比源代码来的更加有价值。如果大家愿意,可以加入我们的群共同讨论。
计划表
每日都在计划表中纠结,一步步辛酸,一步步艰难的前行。
CODE
部分商业核心代码,暂时不予开源。
#include "pf/base/string.h"
#include "pf/base/log.h"
#include "pf/base/time_manager.h"
#include "pf/net/packet/factorymanager.h"
#include "pf/sys/thread.h"
#include "common/define/enum.h"
#include "common/define/macros.h"
#include "common/define/net/packet/id/clientlogin.h"
#include "common/define/net/packet/id/billinglogin.h"
#include "common/define/net/packet/id/logincenter.h"
#include "common/net/packet/client_tologin/ask_login.h"
#include "common/net/packet/login_toclient/ask_login.h"
#include "common/net/packet/login_tocenter/role_kick.h"
#include "common/net/packet/login_tobilling/auth.h"
#include "common/net/packet/billing_tologin/auth.h"
#include "common/net/packet/login_toclient/turn_status.h"
#include "connection/login.h"
#include "engine/system.h"
#include "connection/queue/turn.h"
#include "logic/login/controllers/account.h" using namespace logic::login;
using namespace common::define::net::packet; AccountController::AccountController() {
core_ = NULL;
} AccountController::~AccountController() {
//do nothing
} bool AccountController::setuplayout() {
return true;
} int32_t AccountController::request(uint8_t type, void *data) {
__ENTER_FUNCTION
int32_t result = -;
switch (type) {
case kLogicRequestNet: {
logic_requestnet_t *netdata = static_cast<logic_requestnet_t *>(data);
result = net_handle(netdata);
break;
}
case kLogicRequestUICommand:
break;
case kLogicRequestDB:
break;
default:
break;
}
return result;
__LEAVE_FUNCTION
return -;
} void AccountController::set_core(logic::Interface *core) {
core_ = core;
} logic::Interface *AccountController::get_core() {
return core_;
} int32_t AccountController::ask_login(logic_requestnet_t *netdata) {
__ENTER_FUNCTION
using namespace pf_base::string;
using namespace common::net::packet;
char account[ACCOUNT_LENGTH_MAX] = {};
connection::Login *connection =
dynamic_cast<connection::Login *>(netdata->connection);
client_tologin::AskLogin *packet =
dynamic_cast<client_tologin::AskLogin *>(netdata->packet);
safecopy(account, packet->get_account(), sizeof(account));
if ( == strlen(account) || !checkstr(account, sizeof(account))) {
login_toclient::AskLogin msg;
msg.set_result(kLoginResultAuthFail);
connection->sendpacket(&msg);
SLOW_LOG(LOGIC_MODULENAME,
"[logic.login] (AccountController::ask_login) account is empty."
" account: %s, version: %d",
packet->get_account(),
_MAIN_VERSION);
return kPacketExecuteStatusContinue;
}
connection->setaccount(packet->get_account());
connection->setstatus(kConnectionStatusLoginWaitingAuth);
connection->set_billingtime(TIME_MANAGER_POINTER->get_saved_time());
login_tobilling::Auth *msg = dynamic_cast<login_tobilling::Auth *>(
NET_PACKET_FACTORYMANAGER_POINTER
->createpacket(id::login_tobilling::kAuth));
Assert(msg);
msg->set_account(packet->get_account());
msg->set_password(packet->get_password());
msg->set_connectionid(connection->getid());
msg->set_token(packet->get_token());
msg->set_ip(connection->getsocket()->host_);
CONNECTION_MANAGER_SERVER_POINTER
->syncpacket(msg, kConnectServerTypeBilling);
return kPacketExecuteStatusContinue;
__LEAVE_FUNCTION
return -;
} int32_t AccountController::auth(logic_requestnet_t *netdata) {
__ENTER_FUNCTION
uint64_t current_threadid = pf_sys::get_current_thread_id();
int32_t result = kPacketExecuteStatusContinue;
if (current_threadid == CONNECTION_MANAGER_INCOMING_POINTER->threadid_) {
result = auth_toincomming(netdata);
} else if (current_threadid ==
CONNECTION_MANAGER_LOGIN_POINTER->threadid_) {
result = auth_tologin(netdata);
}
return result;
__LEAVE_FUNCTION
return kPacketExecuteStatusError;
} int32_t AccountController::auth_toincomming(logic_requestnet_t *netdata) {
__ENTER_FUNCTION
using namespace common::net::packet;
billing_tologin::Auth *packet =
dynamic_cast<billing_tologin::Auth *>(netdata->packet);
connection::Login *connection =
dynamic_cast<connection::Login *>(netdata->connection);
if (strcmp(connection->getaccount(), packet->get_account()) != ) {
SLOW_ERRORLOG(LOGIC_MODULENAME,
"[logic.login] (AccountController::auth_toincomming)"
" account error."
" account: %s, packet account: %s",
connection->getaccount(),
packet->get_account());
return kPacketExecuteStatusContinue;
}
uint32_t time = connection->get_billingtime();
enum { kBillingTimeMax = , };
if (TIME_MANAGER_POINTER->get_saved_time() > time + kBillingTimeMax) {
SLOW_DEBUGLOG(LOGIC_MODULENAME,
"[logic.login] (AccountController::auth) time out.");
return kPacketExecuteStatusContinue;
}
if (kConnectionStatusLoginWaitingAuth == connection->getstatus()) {
if (kLoginResultSuccess == packet->get_result() &&
GLOBAL_VALUES["app_status"] != kAppStatusStop) {
connection->setstatus(kConnectionStatusLoginAuthed);
CONNECTION_MANAGER_INCOMING_POINTER->erase(connection);
CONNECTION_MANAGER_LOGIN_POINTER //发送到登陆管理器线程
->sendpacket(packet, connection->getid());
connection->setstatus(kConnectionStatusLoginProcessTurn);
} else {
if (kLoginResultOtherOnline == packet->get_result()) {
//这个暂时用不到
login_tocenter::RoleKick *msg =
dynamic_cast<login_tocenter::RoleKick *>(
NET_PACKET_FACTORYMANAGER_POINTER
->createpacket(id::login_tocenter::kRoleKick));
Assert(msg);
msg->set_account(packet->get_account());
CONNECTION_MANAGER_SERVER_POINTER
->syncpacket(msg, kConnectServerTypeCenter);
}
login_toclient::AskLogin msg;
msg.set_result(packet->get_result());
if (GLOBAL_VALUES["app_status"] == kAppStatusStop) {
msg.set_result(kLoginResultStopService);
}
CONNECTION_MANAGER_LOGIN_POINTER->sendpacket(&msg, connection->getid());
}
}
return kPacketExecuteStatusContinue;
__LEAVE_FUNCTION
return kPacketExecuteStatusError;
} int32_t AccountController::auth_tologin(logic_requestnet_t *netdata) {
__ENTER_FUNCTION
using namespace common::net::packet;
billing_tologin::Auth *packet =
dynamic_cast<billing_tologin::Auth *>(netdata->packet);
connection::Login *connection =
dynamic_cast<connection::Login *>(netdata->connection);
if (strcmp(connection->getaccount(), packet->get_account()) != ) {
SLOW_ERRORLOG(LOGIC_MODULENAME,
"[logic.login] (AccountController::auth_tologin)"
" account error."
" account: %s, packet account: %s",
connection->getaccount(),
packet->get_account());
return kPacketExecuteStatusContinue;
}
CONNECTION_MANAGER_LOGIN_POINTER->add(connection);
login_toclient::AskLogin msg;
msg.set_result(kLoginResultSuccess);
CONNECTION_MANAGER_LOGIN_POINTER->sendpacket(&msg, connection->getid());
uint16_t queuepos = ;
CONNECTION_QUEUE_TURN_POINTER->erase(connection->getaccount(),
connection->getid());
if (CONNECTION_QUEUE_TURN_POINTER->addin(
connection->getid(), connection->getaccount(), queuepos)) {
connection->set_queueposition(queuepos);
connection->set_last_sendmessage_turntime(
TIME_MANAGER_POINTER->get_tickcount());
login_toclient::TurnStatus msg;
msg.set_status(kLoginTurnStatusInTurn);
msg.set_number(
CONNECTION_QUEUE_TURN_POINTER->calculate_turnnumber(queuepos));
connection->sendpacket(&msg);
} else {
SLOW_WARNINGLOG(LOGIC_MODULENAME,
"[logic.login] (AccountController::auth_tologin)"
" the turn is full. account: %s",
connection->getaccount());
CONNECTION_MANAGER_LOGIN_POINTER->remove(connection);
return kPacketExecuteStatusError;
}
return kPacketExecuteStatusContinue;
__LEAVE_FUNCTION
return kPacketExecuteStatusError;
} int32_t AccountController::net_handle(logic_requestnet_t *netdata) {
__ENTER_FUNCTION
if (is_null(netdata) ||
is_null(netdata->connection) ||
is_null(netdata->packet)) return kPacketExecuteStatusError;
int32_t result = kPacketExecuteStatusContinue;
uint16_t packetid = netdata->packet->getid();
switch (packetid) {
case id::client_tologin::kAskLogin:
result = ask_login(netdata);
break;
case id::billing_tologin::kAuth:
result = auth(netdata);
break;
default:
break;
}
return result;
__LEAVE_FUNCTION
return -;
}
开发任务
本次商业版的开发历时两月,主要的任务是完成或至少理清一种游戏服务器构架,并完成PF核心的升级(商业版本的目前版本为1.0.5d)。
完成任务
本次完成了一种服务器的构架,并支持构架扩展(重量级和轻量级)。未完成的任务是游戏的DEMO制作,主要原因是客户端方面引擎的不熟悉,因为本次将使用我未接触过的cocos2dx引擎。
服务器功能
此次的服务器支持共享缓存(以共享内存作为数据缓存,并可以通过缓存进行数据库查询)。服务器分为消费服务器、共享缓存、登陆服务器、数据服务器、中心服务器、游戏服务器。游戏服务器的设计中支持跨服登陆,跨服的数据共享,跨服的数据保存。逻辑系统使用MVC模式,包括脚本都使用统一的模式管理。
性能上此次中心服务器和游戏服务器分别有一个共享缓存服务器,一组正常的服务器至少有七个服务器(其中消费服务器可以共享)。在没有场景服务的测试和压力测试下,服务器的平均负载为0.3,即单个CPU(线程)的占用为30%。内存为游戏服务器支持5000的玩家缓存情况下,占用为1.6G。其中场景和连接的CPU占用和内存消耗占时可以计算出来,争取做到单CPU可以流畅运行,内存最大的峰值(包括脚本占用)为5G即可。
消费服务器功能为账号验证和游戏中点卡或充值服务。
数据服务器为多线程模式,主要提供数据库查询服务器,每个线程对应一个数据库连接器,保证数据库能够快速查询。线程使用线程池管理,分为查询和保存的线程池,将数据库进行读写分离。
共享缓存作为以内存共享为基础,用来对数据进行缓存,主要是数据库方面的缓存。
登陆服务器作为第一个与客户端连接的验证,扮演着网关的角色。
中心服务器作为控制游戏服务器和登陆服务器的中心指挥,作为整个应用中的核心,在中心服务器上存储着角色的在线信息以及全局信息(排行、邮件等功能)。
游戏服务器主要作为玩家逻辑和场景服务使用,在设计中每个游戏服务器可以承载不同的场景,进行分布式数据管理同步(压力分布)。在重量级中,场景数目和复杂度过高的情况下这是必须的。
跨服原理
客户端请求登陆游戏服务器,服务器收到请求会先请求中心服务器进行验证,注意这里的游戏服务器所请求的中心服务器是跨服原服务器所在的服务器。验证成功后,进行共享内存加载数据,共享缓存夸服时存在一张以中心ID为HASH的连接到对应数据服务器的连接ID列表。这样登陆的时候就可以找到玩家所在的数据服务器,进行数据的加载,实现跨服功能。
项目展示
以下只展示linux部分,PF商业版同时支持windows运行。
1、 项目管理器(WEB)
结合PF项目管理文件,可以方便的进行项目管理,主要是用于生成不同平台的编译脚本,以后的功能将会更加完善。
2、 协议管理器(WEB)
这里指的是静态包协议管理,也就是说在发送的时候数据是静态的,也就是说有固定的方法设置和获取数据。在PF核心中支持使用其他协议,如protobuf、amf等。
3、 验证服务器
4、 数据服务器
5、 登陆服务器
6、 中心缓存服务器
7、中心服务器
8、游戏缓存服务器
9、游戏服务器
10、后台运行
开发总结
明日将分享项目管理器和网络包管理器的制作原理。
PF人员招募
开篇语
我们没有大神,只有解决问题的人。
我们没有强悍的技术,只有一颗向往简单的心。
我们没有惊人的理论,只有一堆不可思议的妄想。
我们不需要复杂,只需要够简洁。
我们不需要固定的思维,只需要你能想得到。
PF托管地址
https://github.com/viticm/plainframework1
PF安装教程
http://www.cnblogs.com/lianyue/p/3974342.html
PF交流QQ群
plain framework 商业版 开发总结1 updated的更多相关文章
- plain framework 商业版 开发总结2 项目管理器
任何事情都有三个阶段,分析.制作.质检的过程.在程序中就分为设计.编码.调试(测试)三个阶段,其中设计最为重要,设计的不好会导致编码和调试重复,甚至最后又回到了设计的过程.为了不会重复返工,所以设计的 ...
- 程序设计模式浅析(plain framework商业版设计模式)
程序设计其实对程序开发者来说十分重要,但是在工作中往往我们却忽略了这一块,因为我们所用的都是现有的模式.一个设计模式的好坏,往往能够体现出程序的专业性,还有整个项目的可持续性.这就是为什么有些公司,在 ...
- plain framework 1 一款主要用于网络(游戏)开发的C/C++开源框架 安装篇 updated
上次介绍了一下plain framework的基础相关资料,今天该框架正式开源发布.项目的地址托管于github上,我相信大多数朋友都应该知道.今天要介绍的是该框架的目录基本结构,以及分别在linux ...
- plain framework 1 1.0.4 更新 稳定版发布
PF由于各种因素迟迟不能更新,此次更新主要是更新了以往和上个版本出现的内存问题,该版本较为稳定,如果有用到的朋友请更新至此版本. PF 1.0.4 修复1.0.0.3更新后产生的内存问题,可能导致网络 ...
- plain framework 1(简约框架)一款主要用于网络(游戏)开发的C/C++框架 即将开源发布
在我们的日常开发中,我们往往会遇到这种情况,当我们换了一个开发环境时很可能会重新利用一套新的框架进行开发.由于不同框架有着不同的接口,所以我们不得不花时间再次熟悉这些接口,这将造成开发时间上的重复,而 ...
- plain framework 1 1.0.3更新 优化编译部分、网络压缩和加密
有些东西总是姗姗来迟,就好比这新年的钟声,我们盼望着新年同时也不太旧的一年过去.每当这个时候,我们都会总结一下在过去的一年中我们收获了什么,再计划新的一年我们要实现什么.PF并不是一个十分优秀的框架, ...
- plain framework 1 网络流 缓存数据详解
网络流是什么?为什么网络流中需要存在缓存数据?为什么PF中要采用缓存网络数据的机制?带着这几个疑问,让我们好好详细的了解一下在网络数据交互中我们容易忽视以及薄弱的一块.该部分为PF现有的网络流模型,但 ...
- plain framework 1 参考手册 入门指引之简介
简介 简介 能做什么? LINUX WINDOWS 简介 简约框架(plain framework)是一款基于C/C++开发的,跨平台(windows/linux)应用的基础框架,开发者可以利用此框架 ...
- 关于Eclipse Modeling Framework 实现模型驱动开发,第一部分
======================================EMF第二篇文章========================= 用 Eclipse Modeling Framework ...
随机推荐
- NodeJs+http+fs+request+cheerio 采集,保存数据,并在网页上展示(构建web服务器)
目的: 数据采集 写入本地文件备份 构建web服务器 将文件读取到网页中进行展示 目录结构: package.json文件中的内容与上一篇一样:NodeJs+Request+Cheerio 采集数据 ...
- 通过Matrix进行二维图形仿射变换
Affine Transformation是一种二维坐标到二维坐标之间的线性变换,保持二维图形的"平直性"和"平行性".仿射变换可以通过一系列的原子变换的复合来 ...
- 有向无环图的应用—AOV网 和 拓扑排序
有向无环图:无环的有向图,简称 DAG (Directed Acycline Graph) 图. 一个有向图的生成树是一个有向树,一个非连通有向图的若干强连通分量生成若干有向树,这些有向数形成生成森林 ...
- jquery dataTable汉化(插件形式)
1.jquery dataTable.js 官网:http://datatables.net/ 中文:http://dt.thxopen.com/ 2.汉化提示信息(放到xx.js中,引入即可) 注: ...
- WPF 后台数据触发改变界面状态-心跳实现
今年做的一个上位机工控WPF项目,做个小小的总结把,以后随时来找 请不要带血乱喷,我只是菜鸟.___by 鲍队 类似于这样子的;大致的意思是:一个代码变量,通过改变变量的值,绑定这个变量的这个圆颜色也 ...
- 关于Net Core 多平台程序的Framework问题
关于Net Core 多平台程序的Framework问题: (本文只是推测,欢迎大家指正) 最近在研究NetCore的多平台问题,起因是有一个Winform的项目,由于跨平台的要求,想改为NetCor ...
- Go语言开发
Go语言圣经(中文版) Go编程语言规范 搭建Go开发及调试环境(LiteIDE + GoClipse) -- Windows篇 Go开发工具 Go命令行操作命令详细介绍 ...
- [示例] Firemonkey OnTouch 多点触控应用
说明:Firemonkey OnTouch 多点触控应用,可同时多指移动多个不同控件 原码下载:[原创]TestMultitouchMove_多点触控应用_by_Aone.zip 运行展示:
- STL: unordered_map 自定义键值使用
使用Windows下 RECT 类型做unordered_map 键值 1. Hash 函数 计算自定义类型的hash值. struct hash_RECT { size_t operator()(c ...
- 用Fiddler模拟低速网络环境
有时候宽频网路用习惯了… 在开发的过程就比较少去考虑最佳化的问题… 但当有人反应说「你的网页好慢」甚至当网路速度慢,会造成你的网页跳出什么啊哩不哒的bug时要如何重现呢? 我们可以用Fiddler 这 ...