当前位置: 首页 > news >正文

boost.asio

as(async):异步 

同步io: 

 reactor (非阻塞)(需要注册一次,在等待消息时可以干别的事)   阻塞io网络模型

接口:read\accept\connect\write                接口返回时,io完成

异步io:

iocp (多次投递请求,给菜鸟驿站篮子,让菜鸟驿站把篮子和货物一起送过来)

接口上:WSARecv\AcceptEc\ConnectEx\WSASend    接口返回时,io并未完成

工作中的运用,基于抽象的模型解决问题:

两个命名空间:

boost::aiso

提供核心类以及重要函数

io_context(io上下文):相当于reactor中的对象,相当于windows中IOCP对象

iocp:1.创建一个具体的socket  2.创建一个完成端口,socker绑定在完成端口上

boost::aiso  : 如果socket要异步处理io,必须把socket跟io_context进行绑定

reactor   : epoll   检测  就绪                      非阻塞 io : 操作io(事件循环中处理)

重要函数:

封装的: 同步io函数:posix api类似  标准api:connect    accept    read_some    write_some

                异步io函数:  api     async_connect    async_accept    async_read_some                                                    async_write_some

boost::asio::ip             使用这个命名空间操作协议栈

1.ip地址的封装           ip地址:  ip::address

                                    端点:     ip::tcp::endpoint \  ip::udp::endpoint

服务端绑定:IP port          1.ipv4/ipv6   2.tcp/udp           3.给定具体的端口

socket:     ip::tcp::socket       ip::udp::socket

套接字控制:   set_option  设置套接字属性

                        get_option   

                        io_control    在套接字上执行io指令

cmake 来构建boost.asio应用

boost::system

同步io函数:抛异常   获取错误码

connect(socket,boost::system::error_code err)

异步io函数: buffer(篮子)boost::asio::buffer

                       回调函数:

异步读取数据 :准备一个篮子,如果操作系统帮我们把这个数据都出来后 ,并且填充到里面后 ,会回调函数  :没出错的话:会告诉你往这个篮子放了多长的数据  ,出错了的话:error可以告诉我们没有读取到数据的原因    

篮子就是回调函数,在数据传输完成后会自动触发

async_read_some(buffer(data,lenght)),[](boost::system::error_code err,size_t transferedBytes){

};

创建文件后,根目录是CMakeLists.txt 里面的project相当于解决方案的名字.sln

boost都是以头文件来提供库 #include "asio.h"   #include <boost/asio.hpp>

using namespace boost::asio;

using namespace boost::asio::ip;

io_context相当于reactor对象也相当于一个iocp的对象   io_ctx.run()相当于react中的事件循环,相当于iocp当中的不断地阻塞,等待,完成通知

事件循环:先注册一个事件后,会有不断地事件循环,检测io就绪之后再去操作io

iocp中先投递一个请求到iocp中,iocp会去帮我们完成,然后通知 另外一个线程(这个线程就是一个死循环,不断地从iocp这个完成队列当中取出完成事件)

最开始学习网络编程的思路:

server:首先创建一个socket,是一个listensocket,主要目的是用来接受客户端的连接,bind绑定一个具体的地址,listen用于监听,监听完之后既可以用于接受连接

不同的网络模型,这里的流程都是一摸一样的

boost.asio直接封装了一个对象,这个对象就是acceptor,直接用一个对象进行封装了,acceptor本质上而言是一个socket,所有的socket必须要绑定io_context,否则不能在它的基础上展开异步操作

在这个编程的过程中我们需要进行一个封装,直接使用这个acceptor不太好处理,因为我们在这里接下来会有异步操作,接着又要投递异步操作。对于异步操作而言,虽然io操作不是我们自己的,不是在用户态完成的,但是需要投递一次,完成一次,不是像rector网络编程,他是注册一次,未来只要有数据它就通知你。异步编程或者是boost.asio不会这么灵敏,必须要你投递才会去完成你的事情,否则是不会动的,因为要反复投递,直接用这个对象封装是不太好的。直接去封装一个server,作用是不断接受客户端的连接

//智能指针
include <memory>



//因为要反复进行投递,所以我们要封装一个对象

class Session:public std::enable_sharder_from_this<Session >
{
public::
    Session(tcp::socket sock) socket_move(sock))//链接不能拷贝复制,把socket里面的系统资源移动到这个Session里面的socket上面,移动完后,这个sock就会被析构
    {}
哪些操作:
    void Start(){
//开始读数据
do_read();
private:
    void do_close(){
    boost::system::error_code err;
socket_.close(err);
}  

}
    void do_read(){
    auto self(shared_from_this())
//不断地异步的去读数据
socket_async_read_some(buffer(readBuffer_,max_packet_len),//后面是具体的回调函数
        
        [this,self](boost::system::error_code err,size_t transfered){
            if(err)
        {
            do close;
            return;
        } 
        //希望回调函数调用时,这个socket_依然存在,则使用智能指针
            do_read();

});

void do_write(){
        auto self(shared_from_this())
    socket_async_read_some(buffer(readBuffer_,max_packet_len),
    [this,self](boost::system::error_code,size_t transfered)
{
    if(err){
do_close();
return ;
}
do_read();
}
}



}
}
private:
   
    
    tcp::socket socket_;
    enum  readBuffer_{max_packet_len=1024};

};









//不断接收客户端的连接
class Server{
public:
    server(io_context,short port) :acceptor_(io_ctx,tcp::endpoint(tcp::v4(),port))
{
    //这当中应该要不断地投递出异步请求
}
private:
   void do_accept(){
    acceptor_.async.accept(
    [this](boost::system::error_code err,tcp::socket sock){
    //在这里进行判断是否出现错误,如果没有出现错误,我们就接受了一条新的连接,那我们就需要构建连接,继续进行封装,本来直接在这个sock上抛出异步读数据的请求,进行网络编程,当我们接收到一个客户端的连接之后,要循环往复在这个连接上读数据写数据,一直到这条连接断开为止,所以要基于这个sock反复地去投递不同地读请求或者是写请求 ,所以給这个sock也封装一个对象
    if(!err)
{
    std::make_shared<Session>(sock)->Start();
}

}

)
//第一个参数是一个具体的回调函数,直接给一个回调函数就行了
//第二个参数接受具体的连接,它会直接帮我们构建一个socket
}
//构造函数,server中只有一个变量acceptor_,所以需要
//把io_context传进去,否则构造不会成功,在acceptor上抛异步请求,
//必须要有一个io_context,这个iocontext是我们这个boost.asio命名空间中帮我们构建的
//作为服务端还需要绑定一个端口port
private:
    tcp::acceptor acceptor_;//不断地抛接收连接的请求

};

网络模型可分为以下两大类:

  1. 阻塞/同步模型

    • 线程阻塞等待IO操作完成

    • 典型代表:传统阻塞IO模型

    • 问题:线程资源消耗大,扩展性差

  2. 非阻塞/异步模型

    • Reactor模式:同步非阻塞+事件驱动

    • Proactor模式:异步IO+事件驱动

    • 特点:高并发、资源利用率高

 Boost.Asio

  • 设计特点

    • 跨平台抽象(Windows用IOCP,Linux用epoll)

    • Proactor模式接口,Reactor模式实现(Linux)

    • 支持协程(C++20后)

相关文章:

  • 在 i.MX8MP 上用 C++ 调用豆包 AI 大模型实现图像问答
  • 东方通TongHttpServer报错403
  • RFID技术在机器人中的核心应用场景及技术实现
  • Reactive编程:什么是Reactive编程?Reactive编程思想
  • git中feature跟hotfix是什么意思
  • VSCode:Linux下安装使用
  • 区块链知识点知识点3
  • MybatisPlus(SpringBoot版)学习第六讲:插件(分页插件乐观锁)
  • dom0-kernel: /thermal-zones/soc_max/cooling-maps/map0: could not find phandle 2
  • (C语言)指针运算 习题练习1.2(压轴难题)
  • kali利用msf渗透Windows电脑测试
  • 《Keras 3 :AI 使用图神经网络和 LSTM 进行交通流量预测》
  • 数据结构之多项式相加的链表实现
  • PHP文件的导出和导入
  • 蓝桥杯省模拟赛 01串个数
  • 攻破tensorflow,勇创最佳agent(1)---学习率learning_rate问题
  • 【云服务器】在 Linux(Ubuntu / CentOS 7)上快速搭建我的世界 Minecraft 服务器,并实现远程联机,详细教程
  • 笔记:代码随想录算法训练营day62:108.冗余连接、109.冗余连接II
  • MybatisPlus(SpringBoot版)学习第四讲:常用注解
  • PHP MySQL 预处理语句
  • 赖清德为“临阵脱逃”作准备,国台办:绝不会任“台独”祸首逍遥法外
  • 《克莱默夫妇》导演罗伯特·本顿去世,终年92岁
  • 云南威信麟凤镇通报“有人穿‘警察’字样雨衣参与丧事”:已立案查处
  • 国羽用冠军开启奥运周期,林丹:希望洛杉矶奥运取得更好成绩
  • 季后赛主场优势消失之谜,这事竟然要赖库里
  • 西藏日喀则市拉孜县发生5.5级地震,震源深度10公里