//一个发包的流程
第一个包就是客户端的心跳包,现在加了版本的包
再来看看这个发包打包过程,过程坚持,但理解费劲
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. php设计模式之Proxy(代理模式)和Facade(外观)设计模式

    Proxy(代理模式)和Facade(外观)设计模式它们均为更复杂的功能提供抽象化的概念,但这两种实现抽象化的过程大不相同 Proxy案例中,所有的方法和成员变量都来自于目标对象,必要时,该代理能够对 ...

  2. js闭包理解实例小结

    Js闭包 闭包前要了解的知识  1. 函数作用域 (1).Js语言特殊之处在于函数内部可以直接读取全局变量 <script type="text/javascript"> ...

  3. php 安装xdebug扩展

    php 扩展获取地址 http://pecl.php.net/package/ 编译安装的过程 wget http://pecl.php.net/get/xdebug-2.2.2.tgz tar -z ...

  4. Nginx Location配置语法介绍、优先级说明

    nginx 语法规则:location   [=|~|~*|^~|!~|!~*]    /uri/   { … } location匹配的是$document_uri,$document_uri 会随 ...

  5. C++求等比数列之和

    题目内容:已知q与n,求等比数列之和:1+q+q2+q3+q4+……+qn. 输入描述:输入数据不多于50对,每对数据含有一个整数n(1<=n<=20).一个小数q(0<q<2 ...

  6. C语言-sizeof()与strlen()的区别【转】

    先看看sizeof() 一.sizeof的概念 sizeof是C语言的一种单目操作符,如C语言的其他操作符++.--等.它并不是函数.sizeof操作符以字节形式给出了其操作数的存储大小.操作数可以是 ...

  7. onActivityResult无法调用

    最新项目中使用到了Fragment.在fragment中重载了onActivityResult方法,始终无法调用到. 大体是这样:选择图片的功能纠结了很久,能正常发送选择图片,但是选择后无法调用到on ...

  8. php中的日期

    1.在PHP中获取日期和时间 time()返回当前时间的 Unix 时间戳. getDate()返回日期/时间信息. gettimeofday()返回当前时间信息.date_sunrise()返回给定 ...

  9. Delphi开发的IP地址修改工具

    用Delphi进行开发的,直接修改注册表,需重启电脑后才生效

  10. 【转】MessageBox

    MessageBox对话框是比较常用的一个信息对话框,其不仅能够定义显示的信息内容.信息提示图标,而且可以定义按钮组合及对话框的标题,是一个功能齐全的信息对话框. 1.函数原型及参数 function ...