zoukankan      html  css  js  c++  java
  • eos 源码net_plugin分析

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

    1.png
    async_resolve 传递了lambda表达式,如果err为零,则调用connect连接指定的地址
    2.png
    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重新连接。
    3.png
    连接成功后,调用start_session,开始监听该描述符的读事件,并且开始发送握手消息send_handshake()

    3 bool net_plugin_impl::start_session( connection_ptr con )
    开始连接,内部调用start_read_message(),并且增加连接会话数量。
    4.png
    4 void net_plugin_impl::start_read_message( connection_ptr conn ) 读取消息函数,内部较为复杂。
    5.png
    内部将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()重置请求等状态,
    6.png
    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,确定数据大小。
    7.png
    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)处理消息。
    8.png
    位移代码没看明白,注释的意思是保存序列化前的原始信息。之后,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的定义和实现
    9.png
    msgHandler重载了()运算符,当类msgHandler对象传参(msg)时会调用impl.handle_message(c,msg)。如msgHandler h(msg)实际调用的
    impl.handle_message(c,msg)。
    10.png
    net_message为static_variant类型,static_variant类中实现了visit函数
    11.png
    visit内部调用apply函数,apply函数内部调用了visitor对象传参data,visitor就是上一层的msgHandler。
    12.png
    net_plugin_impl::handle_message 根据参数传入不同,实现了不同的函数调用。
    13.png
    这就是所说的visitor模式。通过net_message(static_variant类型)调用封装的visit函数,visit内部调用了visitor对象的传参,只要重载()(param)就可以实现调用。msgHandler重载operator()(const T& msg),所以调用impl.handle_message(c,msg),而msg为不同类型,所以可实现上面的不同调用。

    谢谢关注我的公众号

  • 相关阅读:
    【JAVA基础】private 的使用
    【nginx】配置文件(模块、反向代理、负载均衡、动静分离)
    【Nginx】命令行安装
    【UNIAPP】websocte实现,功能:指定房间聊天,匿名进入 功能,文字与图片
    【前端JS】input对象图片在线转base64
    【UNIAPP】上传视频,进度条的前台与后端
    【IO阻塞异步】协程使用异步,异步爬虫,异步数据库操作
    【装饰器】原理以及基础使用
    可编程网络DataPath 及XDP
    gitlab 代码协作流程
  • 原文地址:https://www.cnblogs.com/secondtonone1/p/10338805.html
Copyright © 2011-2022 走看看