online游戏服务器架构—用户登录数据组织 .

sprite_t类型的数据结构是核心数据结构,每一个登录用户对应一个,它的初始化在用户登录的时候,此后一直到用户退出或者离线一直保存在系统内存当中,在此过程中该sprite_t数据结构被保存在两个哈希表当中,一个是以用户的id为索引,这个是逻辑相关的,另一个是以此连接的套结字描述符为索引,这个是逻辑无关的:

int parse_protocol(uint8_t *data, int rcvlen, fdsession_t* fdsess)

{

protocol_t pkg;

sprite_t *p, tmp; //tmp是个局部变量,分配于栈上,由于此后的执行续是串行的,也就是说在动态分配sprite_t数据结构于堆上之前并不清除此函数的调用栈帧,因此这里使用局部变量很安全。

int i;

i = 0;

//此处用UNPKG_XX系列解析pkg.len, pkg.ver, pkg.cmd, pkg.id, pkg.ret

p = get_sprite_by_fd(fdsess->fd); //以套结字描述符查找sprite_t数据结构,如果该用户已经登录,那么一定能查找到的,因为用户和online的交互是长连接,如果是登录包,那么肯定查不到,因为这是第一个包

if ((pkg.cmd != PROTO_LOGIN && !p) || (pkg.cmd == PROTO_LOGIN && p) …){

ERROR_RETURN(("pkg error”);

}

if (pkg.cmd == PROTO_LOGIN) {

sprite_t* old = get_sprite(pkg.id); //以id为索引查找该用户是否已经登录

if (old) notify_user_exit(old, -ERR_multi_login, 1); //如果已经登录,那么踢出已经登录的用户

p = &tmp;

memset(p, 0, sizeof(*p));

p->id = pkg.id; //设置用户的id,登录期间一定唯一

p->item_cnt = 0;

p->fd = fdsess->fd; //设置fd,套结字描述符,一定是唯一的

p->fdsess = fdsess;

}

return dispatch_protocol(p, pkg.cmd, data + sizeof (pkg), pkg.len - sizeof (pkg));

}

由此可见,一个sprite_t数据结构连接在两个哈希列表中,一个是套结字描述符为索引的,另一个是用户id为索引的,注意这两个索引都是唯一的索引。每每分配一个sprite_t数据结构都要将之插入到两个哈希表当中,以套结字描述符为索引的查找函数如下:

sprite_t* get_sprite_by_fd(int fd)

{

sprite_t* p = g_hash_table_lookup(all_sprites, &fd);

if ( !p || IS_NPC_ID(p->id) )

return 0;

return p;

}

以用户id为索引的查找函数如下:

static inline sprite_t *get_sprite (uint32_t id)

{

sprite_t *p;

list_for_each_entry (p, &idslots[id % HASH_SLOT_NUM], hash_list)

if (p->id == id)

return p;

return NULL;

}

对于登录包,最终dispatch_protocol会进入到auth_cmd,该函数对用户的一些信息进行一些如MD5之类的验证,然后进入到do_auth函数:

static inline int

do_auth(sprite_t* v)

{

sprite_t* p = add_sprite(v); //该函数将新分配的sprite_t数据结构插入到两个哈希链表当中

notify_user_login(p, 1);

ADD_TIMER_EVENT(p, long_time_min45_in_game, 0, now.tv_sec + 45*60);

ADD_TIMER_EVENT(p, long_time_min10_in_game, 0, now.tv_sec + 10*60);

if (IS_GUEST_ID(p->id)) { //如果是访客的话进入下面流程

enter_map(p, 1, 0); //为访客直接设置地图

rsp_proto_login(p);

return 0;

} else {

return db_get_sprite_with_mail(p);

}

}

sprite_t* add_sprite(sprite_t* v)

{

sprite_t* p = alloc_sprite(v->fd);

*p = *v;

p->stamp = now.tv_sec;

INIT_LIST_HEAD(&p->hash_list);

INIT_LIST_HEAD(&p->map_list);

INIT_LIST_HEAD(&p->timer_list);

list_add_tail(&p->hash_list, &idslots[p->id % HASH_SLOT_NUM]); //插入到以用户id为索引值的哈希链表

return p;

}

static inline sprite_t* alloc_sprite(int fd)

{

sprite_t* p = g_slice_alloc(SPRITE_STRUCT_LEN); //分配一个sprite_t数据结构

p->fd = fd; //初始化一个套结字索引值

g_hash_table_insert(all_sprites, &(p->fd), p); //以套结字描述符为索引插入到全局的哈希链表

++sprites_count;

return p;

}

enter_map是一个很重要的函数,它设置了玩家的地图信息,每一个地图都是一个数据结构map_t,里面包含一个list_head类型的数据结构sprite_list_head,而每一个sprite_t数据结构都有一个list_head类型的map_list,每次初始化完了一个sprite_t之后最终都要调用一个list_add_tail (&p->map_list, &tile->sprite_list_head)将该sprite_t加入到一个map的list当中,这里的list_head就是linux内核中的最常见的list_head数据结构

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/444984.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

leetcode300 最长上升子序列

经典题&#xff0c;不解释&#xff0c;可以看我之前文章。 普通dp public class Solution {public int lengthOfLIS(int[] nums) {if (nums.length 0) {return 0;}int[] dp new int[nums.length];dp[0] 1;int maxans 1;for (int i 1; i < dp.length; i) {int maxval …

Github(5)-开源开发-常见错误

使用github 托管代码简单使用教程--开源开发-常见错误5. github开源开发6. 报错log6.1 fatal: remote origin already exists.6.2 There is no tracking information for the current branch.6.标签管理廖雪峰老师博文学习笔记&#xff1a;https://www.liaoxuefeng.com/wiki/89…

online游戏服务器架构--数据库及事件相关 .

Online服务器的第三部分就是数据层&#xff0c;send_request_to_db开始了数据层的处理逻辑&#xff1a; int send_request_to_db(int cmd, sprite_t* p, int body_len, const void* body_buf, uint32_t id)&#xff1b; 在该函数里首先以懒惰的方式连接数据库服务器&#xff…

leecode5 最长回文子串

给定一个字符串 s&#xff0c;找到 s 中最长的回文子串。你可以假设 s 的最大长度为 1000。 示例 1&#xff1a; 输入: "babad" 输出: "bab" 注意: "aba" 也是一个有效答案。 示例 2&#xff1a; 输入: "cbbd" 输出: "bb"…

libxml解析xml文件的一些总结

libxml -- 解析 XML 文档XML 介绍&#xff1a;XML 和 DOMlibxml 介绍 数据类型 — xmlChar数据结构 创建 XML 文档解析 XML 文档修改 xml 文档Xpath — 处理大型 XML 文档libxml2 库函数要注意的函数读取 xml 文件xml 操作基本结构及其指针类型根节点相关函数 创建子节点相关函…

Linux(7)-正则表达式

正则表达式demo1:在某个文件中寻找命令seddemo2:寻找8位电话号码正则表达式&#xff1a;用来描述或者匹配某一系列符合某个句法队则的字符串或者单个字符串。最初正则表达式&#xff0c;出现在自动控制理论和形式化语言理论中。 Linux 中 find grep sed ls命令都支持正则表达式…

服务器端开发的一些建议

摘要: 本文作为游戏服务器端开发的基本大纲&#xff0c;是游戏实践开发中的总结。第一部分专业基础&#xff0c;用于指导招聘和实习考核&#xff0c; 第二部分游戏入门&#xff0c;讲述游戏服务器端开发的基本要点&#xff0c;第三部分服务端架构&#xff0c;介绍架构设计中的一…

leetcode63 不同路径II

一个机器人位于一个 m x n 网格的左上角 &#xff08;起始点在下图中标记为“Start” &#xff09;。 机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角&#xff08;在下图中标记为“Finish”&#xff09;。 现在考虑网格中有障碍物。那么从左上角到右下角将…

小谈Online-game服务器端设计(1、2)

谈这个话题之前&#xff0c;首先要让大家知道&#xff0c;什么是服务器。在网络游戏中&#xff0c;服务器所扮演的角色是同步&#xff0c;广播和服务器主动的一些行为&#xff0c;比如说天气&#xff0c;NPC AI之类的&#xff0c;之所以现在的很多网络游戏服务器都需要负担一些…

Linux(8)-Linux下的编程开发-C/C++、PHP、JAVA概述

Linux下的编程开发1.C/C语言开发环境的搭建2.PHP开发环境搭建3.JAVA开发环境搭建1.C/C语言开发环境的搭建 方式1:文本编辑器编译器&#xff08;gcc/g&#xff09; Ubuntu 下常用的文本编辑器&#xff1a; Gedit–语法高亮Vim–vi(无比强大无比难用)的改进。字符界面/图形界面…

leetcode55 跳跃游戏 秒杀所有答案

给定一个非负整数数组&#xff0c;你最初位于数组的第一个位置。 数组中的每个元素代表你在该位置可以跳跃的最大长度。 判断你是否能够到达最后一个位置。 示例 1: 输入: [2,3,1,1,4] 输出: true 解释: 我们可以先跳 1 步&#xff0c;从位置 0 到达 位置 1, 然后再从位置 …

小谈Online-game服务器端设计(3)

下面我想来谈谈关于服务器上NPC的设计以及NPC智能等一些方面涉及到的问题。首先&#xff0c;我们需要知道什么是NPC&#xff0c;NPC需要做什么。NPC的全称是&#xff08;Non-Player Character&#xff09;&#xff0c;很显然&#xff0c;他是一个character&#xff0c;但不是玩…

小谈Online-game服务器端设计(4)

在这一章节&#xff0c;我想谈谈关于服务器端的脚本的相关设计。因为在上一章节里面&#xff0c;谈NPC智能相关的时候已经接触到一些脚本相关的东东了。还是先来谈谈脚本的作用吧。   在基于编译的服务器端程序中&#xff0c;是无法在程序的运行过程中构建一些东西的&#xf…

leetcode45 跳跃游戏II 秒杀所有答案

给定一个非负整数数组&#xff0c;你最初位于数组的第一个位置。 数组中的每个元素代表你在该位置可以跳跃的最大长度。 你的目标是使用最少的跳跃次数到达数组的最后一个位置。 示例: 输入: [2,3,1,1,4] 输出: 2 解释: 跳到最后一个位置的最小跳跃数是 2。 从下标为 …

MachineLearning(7)-决策树基础+sklearn.DecisionTreeClassifier简单实践

sklearn.DecisionTreeClassifier决策树简单使用1.决策树算法基础2.sklearn.DecisionTreeClassifier简单实践2.1 决策树类2.3 决策树构建2.3.1全数据集拟合&#xff0c;决策树可视化2.3.2交叉验证实验2.3.3超参数搜索2.3.4模型保存与导入2.3.5固定随机数种子参考资料1.决策树算法…

游戏服务器体系结构

本文描述了一个我所设计的游戏服务器体系结构,其目的是实现游戏服务器的动态负载平衡,将对象从繁忙的服务器转移到相对空闲的服务器中.设计并没有经过具体的测试与验证,仅仅是将自己目前的一些想法记录下来.随着新构思的出现,可能会有所变化. 以下是服务器的逻辑视图,其中忽略…

游戏服务器架构探讨

要描述一项技术或是一个行业&#xff0c;一般都会从其最古老的历史开始说起&#xff0c;我本也想按着这个套路走&#xff0c;无奈本人乃一八零后小辈&#xff0c;没有经历过那些苦涩的却令人羡慕的单机游戏开发&#xff0c;也没有响当当的拿的出手的优秀作品&#xff0c;所以也…

leetcode72 编辑距离

给定两个单词 word1 和 word2&#xff0c;计算出将 word1 转换成 word2 所使用的最少操作数 。 你可以对一个单词进行如下三种操作&#xff1a; 插入一个字符 删除一个字符 替换一个字符 示例 1: 输入: word1 "horse", word2 "ros" 输出: 3 解释: ho…

即时通讯系统架构

有过几款IM系统开发经历&#xff0c;目前有一款还在线上跑着。准备简单地介绍一下大型商业应用的IM系统的架构。设计这种架构比较重要的一点是低耦合&#xff0c;把整个系统设计成多个相互分离的子系统。我把整个系统分成下面几个部分&#xff1a;&#xff08;1&#xff09;状态…

leetcode303 区域和检索

给定一个整数数组 nums&#xff0c;求出数组从索引 i 到 j (i ≤ j) 范围内元素的总和&#xff0c;包含 i, j 两点。 示例&#xff1a; 给定 nums [-2, 0, 3, -5, 2, -1]&#xff0c;求和函数为 sumRange() sumRange(0, 2) -> 1 sumRange(2, 5) -> -1 sumRange(0,…