首先在这里庆祝香港回归祖国的怀抱25周年,想起那年还是一个小学生戴着红领巾和胸章激动不已,实现祖国的统一是每个中华儿女从小的梦想!趁着这欢庆的日子,突然想要写些什么,其实最近也在做一些事,由于工作繁忙加上自身的懒惰,因此对于自己所维护的这个框架感觉有些疏远。但我还是没有忘记8年前,当初实现这个框架的激情和梦想,在这里我用一个具体的例子来看看PF框架到底能做些什么。

  例子

  这次的选择是以一个实际运营的项目做测试,其实我在以前的文章中也提到过这个应用,也许大家都并不陌生,它就是现在还比较火爆的剑侠3,一款多人在线的MMO游戏。网络上很久以前就流出了其部分的源代码,很久以前我也对它经过一定的分析,不过感觉到并没有修复和学习的必要,也就没有再看。现在想来最大的原因就是那份代码缺少的东西太多,就连一些基本的头文件都缺失,那么参考的意义就不大,除非有极深的兴趣和足够的精力。

  这次选择的是几年前稍微完整的一份代码,当然也只是冲着研究和学习的目的,毕竟那么一个大型的项目还是有一定的研究价值,不过想要实际运行并没有那么容易,虽然一份可以32编译的版本,但我是索然无味的。其最大的原因,就是我想要将plain framework(PF)应用到这里面。其实从残缺的代码中可以看到其实确实比较重要的地方就是网络方面,而正好PF拥有这个能力,一切就自此开始了。

  PF的网络

  修复那流出并不太全的代码,最大的就是需要实现网络方面的接口,好在PF主要做这方面的,而在修改这部分代码之前,我还以为可能会费一番周折。可是经过一段时间的思考后,结果就如果下面的短短代码,一切都如同古语说的那样:大道至简!

// 这个线程池目前只用于重连
pf_sys::ThreadPool g_thread_pool(6); void reconnect(
pf_net::connection::Basic *conn,
const std::string &name,
const std::string &ip,
uint16_t port) {
for (;;) {
std::this_thread::sleep_for(std::chrono::milliseconds(5000));
KGLogPrintf(KGLOG_DEBUG,
"reconnect: %s(%s:%d)", name.c_str(), ip.c_str(), port);
auto r = conn->connect(ip.c_str(), port);
if (r) {
get_conn_mgr().add(conn); //线程不安全?
get_conn_mgr().set_connection_name(conn->get_id(), name);
conn->set_name(name);
break;
}
}
}; std::unique_ptr < pf_net::connection::manager::Connector > g_connector;
// static bool g_connector_init{ false };
pf_net::connection::manager::Connector & get_conn_mgr()
{
if (is_null(g_connector)) {
auto connector = new pf_net::connection::manager::Connector;
unique_move(pf_net::connection::manager::Connector, connector, g_connector);
g_connector->callback_disconnect([](pf_net::connection::Basic *conn){
auto flag = conn->get_param("no_reconnect"); // 如果设置了不自动重连...
if (flag == true) return;
std::string ip = conn->socket()->host();
if ('\0' == ip[0]) return;
auto port = conn->socket()->port();
std::string name = conn->name();
conn->set_empty(false);
g_thread_pool.enqueue([conn, name, ip, port]{
reconnect(conn, name, ip, port);
});
});
}
return *g_connector.get();
}

  上面的代码是用于客户端连接的,也就是需要连接到服务器使用,在这个项目的构架中游戏服务器也需要连接到其他服务器的,如中心服和网关。这里在原来的基础上,实现了断线自动重连的功能,原本的服务器是断线后就必须重启所有的进程才能正常工作的,这里做了一点小小的改进,而且实现起来并不复杂。

  那么面向服务器的监听的如何实现呢?其实比较简单,直接使用PF自带的服务进行创建并监听即可,代码如下:

  listener = new pf_net::connection::manager::Listener;
unique_move(pf_net::connection::manager::Listener, listener, listener_);
bRetCode = listener_->init(m_nMaxPlayer, nPort, szIP);
KGLOG_PROCESS_ERROR(bRetCode);

  是不是感觉使用挺容易的?不过到这里功能并没有做完,如果你需要处理连接和断开时的处理则需要注册相应的处理函数(这个是在修复这段代码时,对PF做了一点小小的功能支持调整)。

  代码如下(因为原来的处理客户端连接的代码比较多,这里只截取其中一部分,如果有兴趣可以在残码中找到):

  

  listener_->callback_connect([this] (pf_net::connection::Basic * conn) {
std::pair < KPlayerTable::iterator, BOOL > InsRet;
std::string ip;
KPlayerAgency * pPlayer = NULL;
KG_PROCESS_ERROR(m_PlayerTable.size() < (size_t) m_nMaxPlayer);
while (true) {
KPlayerTable::iterator it = m_PlayerTable.find(m_nNextPlayerIndex);
if (it == m_PlayerTable.end()) {
break;
}
m_nNextPlayerIndex++;
}
...
};
  listener_->callback_disconnect([this] (pf_net::connection::Basic * conn) {
// 该设置在接受连接时进行处理
auto index = conn->get_param("player_index");
std::string ip = conn->socket()? conn->socket()->host() : "";
KPlayerAgency * pPlayer = NULL;
KGLOG_PROCESS_ERROR((index.type != pf_basic::type::kVariableTypeInvalid));
pPlayer = GetPlayer(index.get < int32_t > ());
KGLOG_PROCESS_ERROR(pPlayer);
OnDisconnect(pPlayer);
KGLogPrintf(KGLOG_INFO,
"Player disconnect from %s, index = %d\n",
ip.c_str(), index.get<int32_t>());
Exit0:
return;
});

  由于要配置这个项目的心跳逻辑,因此无法直接使用PF的运行模式(实际上是可以的,不过为了尽可能的改动不多),于是在这里PF又提供了一个基础环境初始化的接口,方便注册网络包的处理以及可以使用日志等接口。

  实现如下:

  // PF basic enviroment.
r = pf_engine::init_basic_env();
KG_PROCESS_ERROR(r);

  使用上面的模式可以脱离pf::Application启动,而且基本的接口都能正常使用,但为了正常的使用,现在需要在你的程序逻辑成功后加上如下代码:

  // 标记启动应用
GLOBALS["app.status"] = kAppStatusRunning;

  关于这份代码

  目前网络上已经有了这个游戏的一键启动,在这里我也放一张进入游戏的图:

  有兴趣的朋友们如果需要学习和研究这份残码,我这里可以简单总结一下,它是10年初的版本,因此大概就是1.5的70版本,网上由于流出的脚本是80的,而且很多的脚本残缺不全,导致了许多的AI甚至物品以及技能无法正常使用。以前也玩过这个游戏,是游戏刚出来的时候(大约09年左右),我觉得这个游戏的技术在当时还是很不错的,无论和画面还是其他各方面在当时国内算得上是前沿。如果作为学习和兴趣,尝试慢慢修复各种脚本需要很长一段时间,就算是比较精通脚本,要达到完整也不容易。

  如果喜欢本游戏的还是建议大家到官网下载该游戏,这款游戏算是目前国内花钱不太多的游戏之一了,而且经过十多年的更替,其画质和各方面都表现的比较出色。

  

  总结

  这次选择使用这段残码作为PF的一个实验,证明了PF在实际应用中还是具有其特性的简单、快速、高效的目的,当然为了完善在实际应用中做了略微的调整。当前PF还是有实际应用的不足,但是我相信在未来可以得到逐步的完善。

  PF2.0的版本或许在将来,使用全新的如C++23进行一次重大更新。

plain framework的实际应用和扩展的更多相关文章

  1. plain framework 1 一款主要用于网络(游戏)开发的C/C++开源框架 安装篇 updated

    上次介绍了一下plain framework的基础相关资料,今天该框架正式开源发布.项目的地址托管于github上,我相信大多数朋友都应该知道.今天要介绍的是该框架的目录基本结构,以及分别在linux ...

  2. 程序设计模式浅析(plain framework商业版设计模式)

    程序设计其实对程序开发者来说十分重要,但是在工作中往往我们却忽略了这一块,因为我们所用的都是现有的模式.一个设计模式的好坏,往往能够体现出程序的专业性,还有整个项目的可持续性.这就是为什么有些公司,在 ...

  3. plain framework 1 参考手册 入门指引之 模块

    模块 总述 基础 数据库 引擎 事件 文件 网络 性能 脚本 系统 工具 总述 上图为plain framework(简称简约框架)所有的模块,包括基础.数据库.引擎.事件.文件.网络.性能.脚本.系 ...

  4. plain framework 1 参考手册 入门指引之简介

    简介 简介 能做什么? LINUX WINDOWS 简介 简约框架(plain framework)是一款基于C/C++开发的,跨平台(windows/linux)应用的基础框架,开发者可以利用此框架 ...

  5. plain framework 商业版 开发总结2 项目管理器

    任何事情都有三个阶段,分析.制作.质检的过程.在程序中就分为设计.编码.调试(测试)三个阶段,其中设计最为重要,设计的不好会导致编码和调试重复,甚至最后又回到了设计的过程.为了不会重复返工,所以设计的 ...

  6. plain framework 1 1.0.4 更新 稳定版发布

    PF由于各种因素迟迟不能更新,此次更新主要是更新了以往和上个版本出现的内存问题,该版本较为稳定,如果有用到的朋友请更新至此版本. PF 1.0.4 修复1.0.0.3更新后产生的内存问题,可能导致网络 ...

  7. plain framework 1 1.0.3更新 优化编译部分、网络压缩和加密

    有些东西总是姗姗来迟,就好比这新年的钟声,我们盼望着新年同时也不太旧的一年过去.每当这个时候,我们都会总结一下在过去的一年中我们收获了什么,再计划新的一年我们要实现什么.PF并不是一个十分优秀的框架, ...

  8. plain framework 1 网络流 缓存数据详解

    网络流是什么?为什么网络流中需要存在缓存数据?为什么PF中要采用缓存网络数据的机制?带着这几个疑问,让我们好好详细的了解一下在网络数据交互中我们容易忽视以及薄弱的一块.该部分为PF现有的网络流模型,但 ...

  9. plain framework 1(简约框架)一款主要用于网络(游戏)开发的C/C++框架 即将开源发布

    在我们的日常开发中,我们往往会遇到这种情况,当我们换了一个开发环境时很可能会重新利用一套新的框架进行开发.由于不同框架有着不同的接口,所以我们不得不花时间再次熟悉这些接口,这将造成开发时间上的重复,而 ...

随机推荐

  1. JavaSE前期准备1

    历史(建议了解即可) 一.1990年,美国Sun公司的"Stealth计划"(后改名为"Green计划")目标设置在家用电器等小型系统的程序语言,准备应用在电视 ...

  2. UnrealEngine创建自定义资产类型

    导语 这篇文章记录了将UObject实例保存在Asset文件的方法,用这个方法可以将自定义的UObject数据序列化保存到文件,可以用于自定义UE资源类型. 创建UObject类 这一步比较简单,按照 ...

  3. 新的 css 子选择器

    1. html 结构 <!DOCTYPE html> <html lang="en"> <head> <meta charset=&quo ...

  4. SQL安装

    安装教程 点击传送 遇到的问题 解决方案1:

  5. 3DUNet的Pytorch实现

    编辑日期: 2021-04-24 16:57:48 本文主要介绍3DUNet网络,及其在LiTS2017肝脏肿瘤数据集上训练的Pytorch实现代码. GitHub地址: https://github ...

  6. 服务器BIOS和BMC等知识详解

    一个执着于技术的公众号 引言:以BIOS为核心的固件产业,是信创产业链的重要组成部分,可被誉为信创产业的"山海关".在计算机体系中,BIOS 有着比操作系统更为底层和基础性的作用, ...

  7. Spring Framework 远程命令执行漏洞(CVE-2022-22965)

    Spring Framework 远程命令执行漏洞 (CVE-2022-22965) 近日,Spring 官方 GitHub issue中提到了关于 Spring Core 的远程命令执行漏洞,该漏洞 ...

  8. 0.1+0.2不等于0.3,微信小程序云开发如何解决JavaScript小数计算精度失准的问题

    先看图 这个是JavaScript语言自身存在的一个问题.说道这里不得不提一下网上流传的JavaScript搞笑图 我们在使用云开发来开发微信小程序的时候,会经常遇到JavaScript小数计算精度失 ...

  9. JavaScript中if语句优化和部分语法糖小技巧推荐

    前言 在前端日常开发过程中,if else判断语句使用的次数应该是比较频繁的了,一些较为复杂的场景,可能会用到很多判断,在某个代码块使用很多if else时,代码会显得较为冗余,阅读起来不够清晰. 除 ...

  10. 手把手教你 bash中给变量赋值时 ' 和 " 和 ` 和 $() 的使用

    1.赋值指令 var='变量内容' var="变量内容" var=`command` var=$(command) var=变量内容 2.格式要求 =两边不能有空白字符 错误示例 ...