1 net_plugin_impl::connect(connection_ptr c) 函数用于解析地址,内部异步回调async_resolve


async_resolve 传递了lambda表达式,如果err为零,则调用connect连接指定的地址

2 void net_plugin_impl::connect( connection_ptr c, tcp::resolver::iterator endpoint_itr ) 该函数将connection连接指定地址
内部调用async_connect进行异步连接,如果连接成功,回调lambda表达式。lambda表达式中取出connection的weak_ptr,这么做为防止shared_ptr互相引用导致内存无法释放。如果连接失败关闭socket连接,如果地址错误关闭socket重新连接。

连接成功后,调用start_session,开始监听该描述符的读事件,并且开始发送握手消息send_handshake()

3 bool net_plugin_impl::start_session( connection_ptr con )
开始连接,内部调用start_read_message(),并且增加连接会话数量。

4 void net_plugin_impl::start_read_message( connection_ptr conn ) 读取消息函数,内部较为复杂。

内部将shared_ptr connection_ptr 赋值给connection_wptr(weak_ptr)类型变量weak_conn,也是为了防止互相引用shared_ptr造成内存无法回收,minimum_read为要读取的字节数,如果conn->outstanding_read_bytes 非0,则等于conn->outstanding_read_bytes,否则等于消息头大小。同时判断是否设置低水位标记,如果设置了低水位标记,则将低水位大小设置为取minimum_read和固定的max_socket_read_watermark的最小值。同时实现lambda表达式赋值给completion_handler,completion_handler主要功能判断传输字节是否全部传输完成。未完成,则返回差值。

5 接着 void net_plugin_impl::start_read_message( connection_ptr conn )内部调用了async_read,设置异步读取数据,有消息到来会触发回调lambada表达式。当completion_handler返回0停止读取。lambda函数内部,conn->outstanding_read_bytes.reset()重置请求等状态,

conn->pending_message_buffer.bytes_to_write()表示pending_message_buffer剩余空间,还可读取多少数据。
conn->pending_message_buffer.
conn->pending_message_buffer.bytes_to_read() 表示pending_message_buffer已经读取多少 字节,用户需要从
pending_message_buffer中读取多少。
conn->outstanding_read_bytes表示buffer还有多少字节没有读取。

判断bytes_transferred > conn->pending_message_buffer.bytes_to_write(),视为异常,因为可用空间不足了 ,没办法接收。
conn->pending_message_buffer.advance_write_ptr(bytes_transferred); 将写指针向后推进bytes_transferred字节。
write_ptr指向了pending_message_buffer的可用空间。bytes_to_write()返回可用字节数。
如果conn->pending_message_buffer.bytes_to_read() > 0,则会一直循环,直到读完buffer中所有数据。
如果bytes_in_buffer < message_header_size,则将头部未读取的数据放入outstanding_read_bytes中。否则说明读完包头数据,pending_message_buffer.peek,读取4字节数据写入message_lenghth,确定数据大小。

auto total_message_bytes = message_length + message_header_size;为整个数据包大小,bytes_in_buffer >= total_message_bytes 说明此时buffer已经接受完数据,调用 conn->process_next_message()处理。否则,就将剩余未读完的数据放入outstanding_read_bytes中,
available_buffer_bytes表示可用字节数,如果可用字节数不足,则扩充pending_message_buffer大小。

6 bool connection::process_next_message(net_plugin_impl& impl, uint32_t message_length)处理消息。

位移代码没看明白,注释的意思是保存序列化前的原始信息。之后,blk_buffer.resize(message_length);重新设置大小为message_length长度,
auto index = pending_message_buffer.read_index();找到当前的读索引,peek函数将message_length长度的数据读入blk_buffer中。
之后创建datastream ds用来反序列化。将消息写入net_message中。接着定义了msgHandler 对象m,构造函数中传入net_plugin_impl和connection共享指针,调用msg.visit(m)。msgHandler的定义和实现

msgHandler重载了()运算符,当类msgHandler对象传参(msg)时会调用impl.handle_message(c,msg)。如msgHandler h(msg)实际调用的
impl.handle_message(c,msg)。

net_message为static_variant类型,static_variant类中实现了visit函数

visit内部调用apply函数,apply函数内部调用了visitor对象传参data,visitor就是上一层的msgHandler。

net_plugin_impl::handle_message 根据参数传入不同,实现了不同的函数调用。

这就是所说的visitor模式。通过net_message(static_variant类型)调用封装的visit函数,visit内部调用了visitor对象的传参,只要重载()(param)就可以实现调用。msgHandler重载operator()(const T& msg),所以调用impl.handle_message(c,msg),而msg为不同类型,所以可实现上面的不同调用。

谢谢关注我的公众号

eos 源码net_plugin分析的更多相关文章

  1. 【精解】EOS标准货币体系与源码实现分析

    EOS智能合约中包含一个exchange合约,它支持用户创建一笔交易,是任何两个基本货币类型之间的交易.这个合约的作用是跨不同币种(都是EOS上的标准货币类型)的,通过各自与EOS主链价值进行锚定,然 ...

  2. 1.EOS源码编译运行

    目前网络上都是针对老版EOS2.0源码编译的文章,我在mac上参考这些文章编译,最后发现根本就不对,最新版本只需一条命令(./eosio_build.sh,依赖库会自动安装的)即可.我根据这些文章手动 ...

  3. MapReduce的ReduceTask任务的运行源码级分析

    MapReduce的MapTask任务的运行源码级分析 这篇文章好不容易恢复了...谢天谢地...这篇文章讲了MapTask的执行流程.咱们这一节讲解ReduceTask的执行流程.ReduceTas ...

  4. Activity源码简要分析总结

    Activity源码简要分析总结 摘自参考书籍,只列一下结论: 1. Activity的顶层View是DecorView,而我们在onCreate()方法中通过setContentView()设置的V ...

  5. MapReduce的MapTask任务的运行源码级分析

    TaskTracker任务初始化及启动task源码级分析 这篇文章中分析了任务的启动,每个task都会使用一个进程占用一个JVM来执行,org.apache.hadoop.mapred.Child方法 ...

  6. TaskTracker任务初始化及启动task源码级分析

    在监听器初始化Job.JobTracker相应TaskTracker心跳.调度器分配task源码级分析中我们分析的Tasktracker发送心跳的机制,这一节我们分析TaskTracker接受JobT ...

  7. MongoDB源码分析——mongod程序源码入口分析

    Edit 说明:第一次写笔记,之前都是看别人写的,觉得很简单,开始写了之后才发现真的很难,不知道该怎么分析,这篇文章也参考了很多前辈对MongoDB源码的分析,也有一些自己的理解,后续将会继续分析其他 ...

  8. FFmpeg的HEVC解码器源码简单分析:解析器(Parser)部分

    ===================================================== HEVC源码分析文章列表: [解码 -libavcodec HEVC 解码器] FFmpeg ...

  9. FFmpeg源码简单分析:libswscale的sws_scale()

    ===================================================== FFmpeg的库函数源码分析文章列表: [架构图] FFmpeg源码结构图 - 解码 FFm ...

随机推荐

  1. 汇编  cdecl 函数调用约定,stdcall 函数调用约定

    知识点:  cdecl 函数调用约定  stdcall 函数调用约定  CALL堆栈平衡 配置属性--> c/c++ -->高级-->调用约定 一.cdecl调用约定 VC++ ...

  2. 微信小程序云开发之云函数创建

    云函数 云函数是一段运行在云端的代码,无需管理服务器,在开发工具内编写.一键上传部署即可运行后端代码. 小程序内提供了专门用于云函数调用的 API.开发者可以在云函数内使用 wx-server-sdk ...

  3. PowerBI开发 第一篇:设计PowerBI报表

    PowerBI是微软新一代的交互式报表工具,把相关的静态数据转换为酷炫的可视化的,能够根据filter条件,对数据执行动态筛选,从不同的角度和粒度上分析数据.PowerBI主要由两部分组成:Power ...

  4. 用Visual Studio2017写C++静态库

    造轮子是一件有趣的事情,VS是一个强大的工具,能胜任超大规模的工程,但是讲真,对不那么大的项目配置起来不是那么友好(网上的其他教程也一点都不友好Orz).这里就展示一下构建一个简单的静态库的正确姿势. ...

  5. Js_封装JQ库为插件

    //在jQuery匿名函数中,采用jQuery.extend();方法创建jQuery插件 //在jQuery匿名函数中, 采用对象.属性 = 函数的方式创建jQuery插件 (function ($ ...

  6. OpenGL(3)-三角形

    写在前面 从这节开始,会接触到很多基本概念,原书我也是读了很多遍,一遍一遍去理解其中的意思,以及他们之间的关系. 概念 顶点数组对象:VAO 顶点缓冲对象:VBO 索引缓冲对象:EBO|IBO Ope ...

  7. 微软职位内部推荐-Software Engineer-Sharepoint

    微软近期Open的职位: SharePoint is a multi-billion dollar enterprise business that has grown from an on-prem ...

  8. 日本厚劳省对IT技术人员展开确保海外人才调查

    新浪美股讯 5月13日消息,共同社报道,日本厚生劳动省将开始对在国内工作的外国籍系统工程师(SE)及程序员的劳动条件进行实际状况调查.为避免在与海外的人才获取竞争中败北,希望掌握接纳企业的需求等推动企 ...

  9. MyBatis3-动态SQL语句

    MyBatis的动态SQL语句是基于OGNL表达式的.可以方便的在SQL语句中实现某些逻辑,总体说来MyBatis动态SQL语句主要有以下几类: 1.if语句(简单的条件判断). 2.choose(w ...

  10. 1079. Total Sales of Supply Chain (25)-求数的层次和叶子节点

    和下面是同类型的题目,只不过问的不一样罢了: 1090. Highest Price in Supply Chain (25)-dfs求层数 1106. Lowest Price in Supply ...