//一个发包的流程
第一个包就是客户端的心跳包,现在加了版本的包
再来看看这个发包打包过程,过程坚持,但理解费劲
void NGP::OnliveTimer()//客户端心跳,5s发一次
{
SendCmd(c2s_on_live, NULL, );
}
bool NGP::SendCmd(int nCmd, void* pData, int nLen)
{
//std::wstring msg = L"发送命令:";
//msg += boost::lexical_cast<std::wstring>(cmd);
//m_share->log(msg.c_str());
//发送获取游戏列表请求
Protocol rpt = {};
rpt.cmd_type = nCmd;
rpt.content = pData;
rpt.size = nLen;
std::vector<char> buffer;
buffer.resize(nLen + sizeof(Protocol));//这个长度个人感觉可以-sizeof(void*),这个位置其实是被覆盖的
int send_len = rpt.to_buffer(&buffer[], buffer.size()); for (;;)
{
bool b = m_spTcpLink->Send(&buffer[], send_len); if (b)
break;
std::this_thread::sleep_for(std::chrono::milliseconds());
} return true;
}
//包的格式(这个就是初始包发送的格式)
-(一个字节的协议)----(四个字节的长度表示后面内容的大小)-----------------(包发的内容)
struct Protocol
{
unsigned char cmd_type;
int size;//content的长度, 不包含本协议头
void* content; int to_buffer(void* buffer, int buffer_len)//挺难理解的
{
if(!buffer)
return -;
int total_size = size + sizeof(Protocol) - sizeof(void*);//- sizeof(void*)是因为到时就是从这个指针的位置开始复制的
if(buffer_len < total_size)//buffer_len是提供的内存大小,total_size是打包后的总大小
return -; Protocol* p = (Protocol*)buffer;//把内存模型看成Protocol模型
p->cmd_type = this->cmd_type;
p->size = this->size;
if (content)
{
memcpy(&p->content, content, size);//从指针开始位置复制内容
}
return total_size;
}
}
//此包在libevent又进行了一次打包过程
----(4个字节,表示后面包的总长度)-(一个字节的协议)----(四个字节的长度表示后面内容的大小)-----------------(包发的内容)
所以对于心跳包的长度是9个字节 //服务端接受到这个包的流程
线程的读事件被调用
/* 读数据流 */
void Channel::read_datastream(struct bufferevent* bev)
{
//bufferevent_read每次会将输入缓冲中的数据读出来,好像最多读4096个字节,那这么大的数据有可能是多个包,还有可能一个包都不到,这是个问题
size_t len = bufferevent_read(bev, m_buf, sizeof(m_buf));
/**
* [测试]:先解锁再加锁,防止此线程在分配内存失败的时候死循环等待时,main_thread的send_data陷入阻塞。
*/
evbuffer_unlock(bev->output); //auto& in = bev->input; lock一样
//auto& out = bev->output;
m_readStream.Push(m_buf, len);//datastream相当于一个缓冲的作用,这个过程看懂废我好大劲,最后还是在同时的帮助下才了解
read_pack(); evbuffer_lock(bev->output);
} void Push(const void * pBuf, int nLen)
{
char* pBuf2 = (char*)pBuf; m_StreamBuffer.insert(m_StreamBuffer.end(), pBuf2, pBuf2 + nLen);//每次将包插入最后一个位置的地方
} /* 读包 */
void Channel::read_pack()
{
if(m_readStream.Size() < )//如果其大小小于4就表示读完了,不可能存在小于4个字节的包,有可能是不完整的包
return; size_t len = *(size_t*)m_readStream.Peek();//获取前四个字节,表示包内容的长度
if( m_readStream.Size() < + len)//表示包不符合规则,应该>=,当然也有可能是因为这个包是不完整的包,等下次再解析
return; m_event->on_receive_data(m_id, m_readStream.Peek() + , len); //对包进行处理
m_readStream.Pop( + len);//每个包逃过下次读取位置 read_pack();//一直读到完为止
}
void Pop(int nLen)
{
m_head_size += nLen;//将头标记移动
if(m_head_size > m_buff_len)
{
//可以将这个数组当成循环队列进行使用,循环队列还有种方式就是两个游标
m_StreamBuffer.erase(m_StreamBuffer.begin(), m_StreamBuffer.begin() + m_head_size);//删掉重新预留,个人理解有可能是防止读取错误,具体不是太清楚
m_head_size = ;
m_StreamBuffer.reserve(m_buff_len);
}
}

关于这个最终到达GS还有很多东西要做,暂时分析到这。

一个包的libevent流程的更多相关文章

  1. 一个包的TcpServer流程

    上次说到对于那种有内容的包 bool TCPServer::on_receive_data(int channel_id, void* data, int len) { packet pkt; { p ...

  2. 一个包的net到gs流程

    再来看看一个包走共享内存的流程 先来看看net进程这块如何处理的 {//用shareData这种类型封装刚才从无锁队列中取到的包 shareData sd; sd.channel_id = pkt.c ...

  3. 【Star CCM+实例】开发一个简单的计算流程.md

    流程开发在CAE过程中处于非常重要的地位. 主要的作用可能包括: 将一些经过验证的模型隐藏在流程中,提高仿真的可靠性 将流程封装成更友好的界面,降低软件的学习周期 流程开发实际上需要做非常多的工作,尤 ...

  4. npm 包的 发布 流程

    npm 包的发布流程 本文主要是针对 还未曾发布过自己的 npm 的同学,阐述一下 npm 的发布流程 熟悉的同学,可以绕道了. 首先你得有一个 自己的 npmjs.com 的账号 (没有的话,就到 ...

  5. Springboot 整合Activiti流程设计器 完成一个简单的请假流程

    目录 1.前言 2.准备 3.下载解压 4.开始整合 mysql + activiti + thymeleaf 2.配置文件 3.复制文件 4.加入控制器 5.修改配置文件 6.剔除启动类里面的安全校 ...

  6. 面试题常考&必考之--http访问一个页面的全流程(Tcp/IP协议)

    分析:-http访问一个页面的全流程,也就好比我们在地址栏输入地址,然后点击回车进行访问 该面试题的主要考点是:计算机网络的TCP/IP协议栈 描述图片:首先应用层提交http请求,传到传输层后由,T ...

  7. pip:带你认识一个 Python 开发工作流程中的重要工具

    摘要:许多Python项目使用pip包管理器来管理它们的依赖项.它包含在Python安装程序中,是Python中依赖项管理的重要工具. 本文分享自华为云社区<使用Python的pip管理项目的依 ...

  8. 判断一个Activity 判断一个包 是否存在于系统中 的方法

    判断一个包是否存在于系统中(来自网络),经过测试,好用: public boolean checkBrowser(String packageName) { if (packageName == nu ...

  9. python高级编程 编写一个包1

    #目的是:编写,发行python包可重复过程"""1:是缩短开始真正工作之前所需要的设置时间,也就是提供模板2:提供编写包的标准化方法3:简化测试驱动开发方法的使用4:为 ...

随机推荐

  1. C# MongoDB--时区问题(差了8小时)

    原因:MongoDB中存储的时间是标准时间UTC +0:00C#的驱动支持一个特性,将实体的时间属性上添加上这个特性并指时区就可以了.例如:[BsonDateTimeOptions(Kind = Da ...

  2. mysql批量修改表引擎

    生成修改的语句 SELECT CONCAT('ALTER TABLE ',table_name,' ENGINE=InnoDB;') FROM information_schema.tables WH ...

  3. python网页请求urllib2模块简单封装代码

    这篇文章主要分享一个python网页请求模块urllib2模块的简单封装代码. 原文转自:http://www.jbxue.com/article/16585.html 对python网页请求模块ur ...

  4. C高级 服务器内核分析和构建 (一)

    引言 最经看cloud wind 的 skynet服务器设计. 觉得特别精妙. 想来个专题先剖析其通信层服务器内核 的设计原理. 最后再优化.本文是这个小专题的第一部分, 重点会讲解对于不同平台通信基 ...

  5. 苹果内付费 IAP

    创建app内购买项目 消耗型项目:对于消耗型App内购买项目,用户每次下载时都必须进行购买.一次性服务通常属于消耗型项目,例如钓鱼App 中的鱼饵. 非消耗型项目:对于非消耗型App内购买项目,用户仅 ...

  6. 10 款提高开发效率的 jQuery/CSS3 组件

    前端开发是一项十分繁琐而又耗体力的工作,如何更有效率的开发我们的应用,很多人会选择适当地使用一些jQuery插件.今天就要给大家分享10款可以提高开发效率的jQuery/CSS3组件.部分插件可以下载 ...

  7. 网站网页生成.shtml访问无法显示

    网站换了服务器后发现shtml网页无法访问,原因是没有注册.shtml扩展名,解决方法如下 IIS6.0解析shtm,shtml文件由于IIS6.0的安全性较以前有特别大的改进,所以在很多功能默认情况 ...

  8. [原创]PostgreSQL Plus Advanced Server批量创建分区表写入亿级别数据实例

    当前情况:大表的数据量已接近2亿条我的解决思路:为它创建n*100个分区表,将各个分区表放在不同的tablespace上这样做的优点:1.首先是对这个级别的数据表的性能会有所提升2.数据管理更科学3. ...

  9. hdu 5427 A problem of sorting

    题目连接 http://acm.hdu.edu.cn/showproblem.php?pid=5427 A problem of sorting Description There are many ...

  10. iOS UI高级之网络编程(HTTP协议)

    HTTP协议的概念 HTTP协议,Hyper Text Transfer Protocol (超文本传输协议)是用于从万维网服务器传送超文本到本地浏览器的传输协议,HTTP是一个应用层协议,由请求和响 ...