首页 > 编程语言 >boost.asio 异步网络编程

boost.asio 异步网络编程

时间:2024-09-25 11:15:07浏览次数:10  
标签:asio 异步 函数 std session 回调 boost 客户端

Proactor 模式
Proactor 模式是一种异步 I/O 处理模式,常用于高性能网络服务器和并发系统中。与传统的 Reactor 模式(基于事件驱动的 I/O 多路复用)不同,Proactor 模式使用异步 I/O 操作来处理 I/O 任务,从而提高了系统的并发能力和响应速度。
1)异步
优点:异步编程有助于提高应用程序的响应性和性能,特别是在涉及大量I/O操作或网络请求的应用场景下。常见的异步编程技术包括回调函数、事件循环、Promise(在JavaScript中)、协程(如Python的asyncio)等。这些技术可以帮助开发者构建高效、非阻塞的系统。

异步示例:
程序执行到“读取文件”操作,并启动该操作。
程序不会等待文件读取完成,而是继续执行后面的指令。
当文件读取完成后,通过回调函数、事件通知或其他机制来处理读取的结果。

2)使用回调函数的异步例子

#include <iostream>
#include <thread>
#include <functional>

// 模拟一个耗时的任务
void simulateLongRunningTask(std::function<void(int)> callback)
{
    std::this_thread::sleep_for(std::chrono::seconds(3)); // 模拟3秒延时
    int result = 42; // 模拟任务结果
    callback(result); // 完成时调用回调函数
}

int main()
{
    // 创建一个lambda函数作为回调
    auto callback = [](int result) {
        std::cout << "异步操作完成,结果为: " << result << std::endl;
    };

    // 启动一个新线程来执行异步任务
    std::thread worker(simulateLongRunningTask, callback);

    // 主线程继续执行其他任务
    std::cout << "主线程继续工作..." << std::endl;

    // 等待异步任务线程结束
    worker.join();

    return 0;
}

在这个例子中,simulateLongRunningTask函数模拟了一个耗时较长的任务,并在任务完成后调用了传递给它的回调函数callback。主函数main创建了一个新的线程来执行这个任务,并且在新线程中执行任务的同时,主线程能够继续执行其他任务。worker.join()用于等待新线程完成其任务。

3)一个简单echo异步服务器引出的问题

“Echo”模式通常指的是一个简单的通信模式,其中服务器接收来自客户端的数据,并将其原样返回给客户端。这种模式经常用于测试网络连接和协议栈的正确性,也可以作为教学示例来演示基本的网络编程概念。

a)问题1:当服务器收到数据将要应答时客户端断开,此时

调用 async_write 触发发送回调:
即使客户端已经断开连接,服务器仍然会尝试调用 async_write 发送数据。由于客户端已经断开,async_write 的回调函数会被触发,并且错误码 ec 会是非零值。
调用析构函数析构session
客户端关闭后触发读就绪事件:
客户端断开连接后,在 TCP 层面上,服务器会收到一个读就绪事件。这是因为 TCP 协议在连接关闭时会发送 FIN 包,这可能会导致服务器误以为有数据可读。
在读回调函数中,再次触发析构函数

现象:出现两次析构
解决方法:将session智能指针存到map中,此时智能指针会自动析构,再在读写出错时调用clean清除map中uuid

b)问题2:重复之前的步骤,在服务器会先触发写回调函数的错误处理,再触发读回调函数的错误处理,这样session就会两次从map中移除,因为map中key唯一,所以第二次map判断没有session的key就不做移除操作了。
但是这么做程序会奔溃;
原因:写和读操作中,回调函数会两次调用session的内存,第一次调用时session的内存已经被析构(从map中移除时自动析构),第二次访问内存时奔溃

解决办法:
将session生命周期与回调函数绑定
此时需要在第一次绑定读写回调函数的时候传入智能指针的值

需要从一个对象内部获取一个指向自身的指针。如果这个对象是由 std::shared_ptr 管理的,那么直接返回 this 指针是不够的,因为 this 指针是一个裸指针,它无法提供对象的生命周期管理信息。
std::enable_shared_from_this 提供了一种方法,使得可以从对象内部返回一个 std::shared_ptr,从而在保证对象生命周期的同时,也能够安全地访问对象。

通过shared_from_this()函数返回智能指针,使用这个函数需要继承类std::enable_shared_from_this

void CSession::Start(){
    memset(_data, 0, MAX_LENGTH);
    _socket.async_read_some(boost::asio::buffer(_data, MAX_LENGTH), std::bind(&CSession::HandleRead, this, 
        std::placeholders::_1, std::placeholders::_2, shared_from_this()));
}

4)asio线程池
从 Boost 1.72 版本开始,Boost.Asio 引入了 boost::asio::thread_pool 类,这是一个专门用于管理线程池的类,简化了线程池的创建和管理。

标签:asio,异步,函数,std,session,回调,boost,客户端
From: https://www.cnblogs.com/light-LifeClub/p/18405869

相关文章

  • 基于异步通讯事件触发的二阶离散系统同步算法设计
    精确计时在时间敏感的工业物联网(IIoT)中起着关键作用。然而,精确的时间同步需要更频繁的数据包交换,这会消耗更多的通信带宽和能量。这在电池供电的无线节点中是一个特别的挑战,低通信成本已成为时钟同步的重要因素。为了应对分布式无线传感器网络中实现低通信成本时钟同步的挑......
  • 使用Promise将异步操作变为同步
    letpromise=newPromise(function(resolve,reject){//异步操作letsuccess=true;//这是一个假设的条件if(success){resolve("操作成功");}else{reject("操作失败");}});Promise可以处于以下三种状态之一:Pending(......
  • 多维时序 | 融合模拟退火和自适应变异的混沌鲸鱼优化算法(AAMCWOA)优化LSTM长短期记忆网
    多维时序|融合模拟退火和自适应变异的混沌鲸鱼优化算法(AAMCWOA)优化LSTM长短期记忆网络结合AdaBoost时间序列预测(AAMCWOA-LSTM-AdaBoost时序预测)目录多维时序|融合模拟退火和自适应变异的混沌鲸鱼优化算法(AAMCWOA)优化LSTM长短期记忆网络结合AdaBoost时间序列预测(AAMCWOA-LSTM-A......
  • 一个.NET开源、快速、低延迟的异步套接字服务器和客户端库
    前言最近有不少小伙伴在问:.NET有什么值得推荐的网络通信框架?今天大姚给大家分享一个.NET开源、免费(MITLicense)、快速、低延迟的异步套接字服务器和客户端库:NetCoreServer。项目介绍NetCoreServer是一个.NET开源、免费(MITLicense)、快速、低延迟的异步套接字服务器和客户端库。它支......
  • XGBoost6种优化算法分类模型一键对比 +交叉验证 Matlab代码
    ......
  • 用Asio实现同步echo服务器
    使用Asio实现同步echo服务器服务端sync_server.h#ifndefASYNC_SERVER_H#define ASYNC_SERVER_H#include<boost/asio/ip/tcp.hpp>#include<memory>#include<set>#include<thread>namespaceMS{ typedefstd::shared_ptr<boost::asio::ip::......
  • fastapi-events fastapi 异步事件分发处理扩展
    fastapi-eventsfastapi异步事件分发处理扩展,提供了本地,以及远程消息处理能力,同时包含了一些内置的handler,对于自定义handler也是比较灵活的参考使用app.pyfromfastapiimportFastAPIfromfastapi.requestsimportRequestfromfastapi.responsesimportJSONResponsefrom......
  • 异步处理方案
    前言良好的系统设计必须要做到开闭原则,随着业务的不断迭代更新,核心代码也会被不断改动,出错的概率也会大大增加。但是大部分增加的功能都是在扩展原有的功能,既要保证性能又要保证质量,我们往往都会使用异步线程池来处理,然而却增加了很多不确定性因素。由此我设计了一套通用的异步处理......
  • 面试-JS异步进阶
    面试题:......
  • asio的同步和异步读写
    同步读写的优缺点缺点:读写是阻塞的,如果客户端不发送数据的话,服务器就会一直阻塞在read上,导致服务器一直处于等待状态。一般是通过开辟一个新的线程来服务客户端的请求,但是一个进程可以开辟的线程数是有限的,大约为2048个,在linux环境下可以通过unlimit增加线程数,但是线程过多也......