本文根据云风博客为思路来解读databuffer在skynet老版本gate服务的应用。
源码为databuffer.h和service_gate.c
首先解释一下什么是ringbuffer
它是一个环(首尾相接的环),你可以把它用做在不同上下文(线程)间传递数据的buffer.

优点 它是一个数组(连续的内存),比链表快。在硬件级别,数组中的元素是会被预加载的,因此在ringbuffer当中,cpu无需时不时去主存加载数组中的下一个元素。
其次你可以为数组预先分配内存。不需要花大量时间用于垃圾回收。

ringbuffer在skynet gate服务中的应用
在旧的gate服务中,skynet启动gate服务,监听一个端口,然后该服务要处理连接到这个端口的所有TCP连接。Skynet使用了一个ringbuffer缓存了所有连接发过来的数据包。然后在一条一条数据去
进行逻辑分包。
ringbuffer的数据结构如下

struct messagepool_list {struct messagepool_list *next;struct message pool[MESSAGEPOOL]; //数组长度是1023
};
messagepoll数据绑定在gate数据上。messagepoll结构里有个messagepool_list的数组,即环形数组
struct messagepool {struct messagepool_list * pool;struct message * freelist;
};

databuffer数据是绑定在每一条tcp连接上。所以databuffer是n,messagepoll是1

struct databuffer {int header; // 约定的包头长度 2或者4int offset;int size; // 该条tcp连接,已经接收到数据大小。 databuffer_push 是加 datebuffer_read是减struct message * head; // 头指针  message数据最终是存在messagepool_list数组里struct message * tail; // 尾指针
};

datebuffer_read 是 去messagepool读指定 sz(2字节或4字节)的消息。

databuffer_read(struct databuffer *db, struct messagepool *mp, char * buffer, int sz) {assert(db->size >= sz); // sz 为2 或者 4db->size -= sz; // size是该条连接已经缓存还没读的消息大小。 现在需要读sz个大小的数据出来.for (;;) {struct message *current = db->head;int bsz = current->size - db->offset;if (bsz > sz) { // 这条message的大小已经够读了,并且还有数据多。多出来的数据说明是下一个逻辑包的数据,这里需要用offset来标记。memcpy(buffer, current->buffer + db->offset, sz);db->offset += sz;return;}if (bsz == sz) { // 已经读出了一个完整的包memcpy(buffer, current->buffer + db->offset, sz);db->offset = 0;_return_message(db, mp); // 回收该内存 db->head往下跳一格return;} else { // 还没读完,需要跳到下一个message去继续读数据。 memcpy(buffer, current->buffer + db->offset, bsz);_return_message(db, mp); // 回收该内存 db->head往下跳一格 并且标记messagepool的freelist为这个已经read的messagedb->offset = 0;buffer+=bsz;sz-=bsz;}}
}static void
databuffer_push(struct databuffer *db, struct messagepool *mp, void *data, int sz) {struct message * m;if (mp->freelist) {m = mp->freelist;mp->freelist = m->next;} else { // ringbuff的数组初始化。struct messagepool_list * mpl = skynet_malloc(sizeof(*mpl));struct message * temp = mpl->pool;int i;for (i=1;i<MESSAGEPOOL;i++) {temp[i].buffer = NULL;temp[i].size = 0;temp[i].next = &temp[i+1];}temp[MESSAGEPOOL-1].next = NULL;//最后一个m的next是空 但freelist指针指向数组最后一个元素时。数组会进行回绕。然后第38行到41行。会把当前的//数组的元素往后移动一格。这里实现非常巧妙。mpl->next = mp->pool;mp->pool = mpl;m = &temp[0]; // 第一个m存储当前push进来的数据mp->freelist = &temp[1]; // freelist指向第二个m}m->buffer = data;m->size = sz;m->next = NULL;db->size += sz; // 标记databuff又接收了sz个数据。等待下次read。if (db->head == NULL) {assert(db->tail == NULL);db->head = db->tail = m;} else {db->tail->next = m;db->tail = m; // 尾指针后移}
}
static inline void
_return_message(struct databuffer *db, struct messagepool *mp) {struct message *m = db->head;if (m->next == NULL) {assert(db->tail == m);db->head = db->tail = NULL;} else {db->head = m->next;}skynet_free(m->buffer);m->buffer = NULL;m->size = 0;m->next = mp->freelist; // freelist是下个tcp进来需要存放的地址,这里db->head的message进行回收,把freelist指针指向这里。下次数据进来就会存放在这里了。mp->freelist = m;
}

【2.skynet c gate服务中databuffer解析(解包)】相关推荐

  1. java event sourcing_使用Spring Cloud和Reactor在微服务中实现EventSourcing -解道Jdon

    使用Spring Cloud和Reactor在微服务中实现Event Sourcing 当在微服务架构中构建应用时,状态管理成为分布式系统的问题,相比于传统monolithic应用,将状态管理通过事务 ...

  2. 实时通信服务中的语音解混响算法实践

    导读: 随着音视频通信会议越来越普及,与会各方在不同环境中遇到了越来越明显且差异的混响场景,譬如大会议室场景.玻璃会议室场景和小房间且隔音材料不佳场景等.为了保证更好的听音可懂度和舒适度,通信中的语音 ...

  3. python 中参数 ,解包和变量的入门

    from sys import argv scrip,first,second,third=argvprint('',scrip) print('',first) print('',second) p ...

  4. 详解Python中的序列解包(2)

    8个月前曾经发过一篇关于序列解包的文章,见详解Python序列解包,本文再稍作补充. 可以说,序列解包的本质就是把一个序列或可迭代对象中的元素同时赋值给多个变量,如果等号右侧含有表达式,会把所有表达式 ...

  5. I3S服务中属性数据解析——基于JS的编程方式

    I3S数据发布服务后,属性数据的查询其实非常麻烦的,而且特别的不友好.所以本文至少抛转引玉. 第一步:尝试获得属性的地址, 由于I3S是以树的结构来存储的,所以叶子节点的数据是最全的.要获得哪些节点是 ...

  6. im中的定位消息 ios_iOS消息发送失败和消息进度回调中msgId没有解包

    /// 重新发送消息 /// [msgId] 原消息的ID /// [receiver] 消息接收者的 userID, 如果是发送 C2C 单聊消息,只需要指定 receiver 即可. /// [g ...

  7. 基于skynet设计游戏服务端框架

    skynet并不是一个开箱即用的服务端框架,游戏后端在开展业务时,需要根据自身业务特点,合理设计相应的服务端框架.在这里我根据自身的设计目标,写下各方面的选择与取舍.对于小型企业来说,一些商业化的软件 ...

  8. python中的装包与解包*,**

    学习过程中遇到了*解包的过程,很感兴趣,于是实验一番, a = (1, 2, 3, 4, 5, 6) b = [2, 3, 4, 5, 5, 6] c = {"name": 'zh ...

  9. Dubbo中暴露服务的过程解析

    原文链接 dubbo暴露服务有两种情况,一种是设置了延迟暴露(比如delay="5000"),另外一种是没有设置延迟暴露或者延迟设置为-1(delay="-1" ...

最新文章

  1. 通过解决“构造包含所有给定子串的最短字符串”问题思考算法优化
  2. python编程入门书-编程小白的第一本 Python 入门书
  3. centos ftp服务器搭建_CentOS系统云服务器宝塔面板安装以及微信小程序服务器搭建...
  4. 斯坦福大学机器学习第三课“多变量线性回归“
  5. Linux CentOS6离线安装Jupyter notebook
  6. 关于二分查找 使用 lower_bound
  7. 消息称百度网盘青春版降速23倍:从52MB/s降至2.2MB/s
  8. 页面的title为乱码的话需要修改jsp页面pageEncoding=UTF-8
  9. 弹簧式止回阀行业调研报告 - 市场现状分析与发展前景预测(2021-2027年)
  10. 招人了!MySQL 面试必须掌握的 8 个知识点!
  11. 解决首次在eclipse中使用maven构建hadoop等项目时报Missing artifact sun.jdk:tools:jar:1.5.0的问题...
  12. Luogu2261 [CQOI2007]余数求和
  13. ASP.NET Core SignalR +微信小程序整理(一)
  14. WebLogic安装教程
  15. 小程序 字号设置 slider滚动改变大小_Snipaste(滚动截图软件)app下载|Snipaste(滚动截图软件) 1.15.2 绿色版(32/64位)...
  16. 蚂蚁金融科技:两大发布,实力开放
  17. 【转】10种吓跑财神的漏财风水
  18. C语言枚举类 口袋中有红、黄、蓝、白、黑5种颜色的球若干个
  19. 网页怎么退出全屏,网页退出全屏有哪些快捷键?
  20. 啥也不懂,实现Deepin系统如何有效安装TL-WDN5200H v2.0 linux驱动,自测成功

热门文章

  1. word文档保存的时候,就会出现“文件许可权错误,word 无法完成保存文件”的提示
  2. 基于 python 的语音识别 API 调用
  3. springMVC+ajax分页查询
  4. 老外常用的网络英文缩写
  5. c语言中tho什么意思,干货丨与老外聊天常用的英文缩写,速度get
  6. 阜和SAP FICO模块课程
  7. 移动云瞄准“一流云商”焕新出发
  8. python中输入直角三角形的两个直角边a,b求斜边c的长度
  9. win8.1 update1使用初体验
  10. APP推广前,你应该知道的事