boost 异步服务器开发

news2024/11/25 4:34:10

目录

1、 异步服务器简介

2、异步服务器开发

2.1 会话类

2.1.1 会话类头文件

2.1.2 会话类源文件

2.2 服务类

2.2.1 服务类头文件

2.2.2 服务类源文件

2.3 主函数

3、异步服务器测试

4、当前异步服务器存在的问题及后续优化


1、 异步服务器简介

        boost 异步服务器分为会话类、服务类, 会话类主要负责与客户端通信, 服务类用来接收客户端连接。

2、异步服务器开发

2.1 会话类

2.1.1 会话类头文件

/**
 * @file session.h
 * @author wangdong (wangdong1328@163.com)
 * @brief 异步服务器开发 会话类
 * @version 0.1
 * @date 2023-06-20
 *
 * @copyright Copyright (c) 2023
 *
 */

#ifndef __SESSION_H__
#define __SESSION_H__

#include "boost/asio.hpp"
#include <iostream>
#include <memory>
#include "boost/uuid/random_generator.hpp"
#include "boost/uuid/uuid_io.hpp"

using boost::asio::ip::tcp;

class CServer;

class CSession
{
public:
    CSession(boost::asio::io_context &ioc, CServer *pServer);

    /**
     * @brief Get the Socket object
     *
     * @return tcp::socket&
     */
    tcp::socket &GetSocket() { return m_socket; }

    /**
     * @brief 开始接收客户端消息
     *
     */
    void Start();

    /**
     * @brief Get the Uuid object
     *
     * @return std::string  会话类唯一ID
     */
    std::string GetUuid() { return m_strUuid; }

private:
    /**
     * @brief 处理读回调
     *
     * @param ec 读回调故障码
     * @param bytes 读取字节
     */
    void HandleRead(const boost::system::error_code &ec, size_t bytes);

    /**
     * @brief 处理写回调
     *
     * @param ec 写回调故障码
     */
    void HandleWrite(const boost::system::error_code &ec);

private:
    // 创建通信socket
    tcp::socket m_socket;
    // 创建服务器指针
    CServer *m_pServer;
    // 会话类唯一ID
    std::string m_strUuid;

    enum
    {
        MAX_BUFFER_SIZE = 1024,
    };

    // 读缓冲区
    char m_arrBuffer[MAX_BUFFER_SIZE];
};

#endif /* __SESSION_H__ */

2.1.2 会话类源文件

#include "session.h"
#include "server.h"

CSession::CSession(boost::asio::io_context &ioc, CServer *pServer)
    : m_socket(ioc), m_pServer(pServer)
{
    // 生成唯一ID, 也可以自己实现雪花算法
    boost::uuids::uuid uuid = boost::uuids::random_generator()();
    m_strUuid = boost::uuids::to_string(uuid);

    // 初始化读缓冲区
    memset(m_arrBuffer, 0, MAX_BUFFER_SIZE);
}

void CSession::Start()
{
    m_socket.async_read_some(
        boost::asio::buffer(m_arrBuffer, MAX_BUFFER_SIZE),
        std::bind(&CSession::HandleRead, this, std::placeholders::_1, std::placeholders::_2));
}

void CSession::CSession::HandleRead(const boost::system::error_code &ec, size_t bytes)
{
    if (!ec)
    {
        std::cout << "recv:" << m_socket.remote_endpoint().address().to_string() << ":" << m_arrBuffer << std::endl;

        m_socket.async_write_some(boost::asio::buffer(m_arrBuffer, bytes),
                                  std::bind(&CSession::HandleWrite, this, std::placeholders::_1));
    }
    else
    {
        std::cout << "error: " << ec.message() << std::endl;

        m_pServer->ClearSession(m_strUuid);
    }
}

void CSession::HandleWrite(const boost::system::error_code &ec)
{
    if (!ec)
    {
        m_socket.async_read_some(
            boost::asio::buffer(m_arrBuffer, MAX_BUFFER_SIZE),
            std::bind(&CSession::HandleRead, this, std::placeholders::_1, std::placeholders::_2));

        // 初始化读缓冲区
        memset(m_arrBuffer, 0, MAX_BUFFER_SIZE);
    }
    else
    {
        std::cout << "error: " << ec.message() << std::endl;

        m_pServer->ClearSession(m_strUuid);
    }
}

2.2 服务类

2.2.1 服务类头文件

/**
 * @file server.h
 * @author wangdong (wangdong1328@163.com)
 * @brief 服务器开发
 * @version 0.1
 * @date 2023-06-20
 *
 * @copyright Copyright (c) 2023
 *
 */

#ifndef __SERVER_H__
#define __SERVER_H__

#include "session.h"
#include <map>

class CServer
{
public:
    CServer(boost::asio::io_context &ioc, unsigned short usPort);

    /**
     * @brief 清理会话类对象
     *
     * @param strUuid
     */
    void ClearSession(const std::string &strUuid);

private:
    /**
     * @brief 开始接收客户端连接
     *
     */
    void StartAccept();

    /**
     * @brief 处理接收到服务器处理
     *
     * @param pSession 会话类指针
     * @param ec 故障码
     */
    void HandleAccept(std::shared_ptr<CSession> pSession, const boost::system::error_code &ec);

private:
    // io上下文
    boost::asio::io_context &m_ioc;
    // tcp接收器
    tcp::acceptor m_acceptor;
    // 会话管理器
    std::map<std::string, std::shared_ptr<CSession>> m_mapSessions;
};

#endif /* __SERVER_H__ */

2.2.2 服务类源文件

#include "server.h"

CServer::CServer(boost::asio::io_context &ioc, unsigned short usPort)
    : m_ioc(ioc), m_acceptor(ioc, tcp::endpoint(tcp::v4(), usPort))
{
    StartAccept();
}

void CServer::ClearSession(const std::string &strUuid)
{
    m_mapSessions.erase(strUuid);
}

void CServer::StartAccept()
{
    // 创建会话类
    std::shared_ptr<CSession> pSession = std::make_shared<CSession>(m_ioc, this);

    m_acceptor.async_accept(pSession->GetSocket(), std::bind(&CServer::HandleAccept,
                                                             this, pSession, std::placeholders::_1));
}

void CServer::HandleAccept(std::shared_ptr<CSession> pSession,
                           const boost::system::error_code &ec)
{
    if (!ec)
    {
        pSession->Start();
        m_mapSessions.insert(std::make_pair(pSession->GetUuid(), pSession));
    }
    else
    {
        std::cerr << "Exception: " << ec.message() << std::endl;
    }

    // 再次等待接收
    StartAccept();
}

2.3 主函数

/**
 * @file main.cpp
 * @author wangdong (wangdong1328@163.com)
 * @brief 异步服务器开发 程序入口
 * @version 0.1
 * @date 2023-06-20
 *
 * @copyright Copyright (c) 2023
 *
 */
#include "server.h"

int main(int argc, char *argv[])
{
    try
    {
        // 创建IO上下文
        boost::asio::io_context ioc;

        // 创建服务器
        CServer server(ioc, 10086);

        // 处理事件循环并阻塞主线程
        ioc.run();
    }
    catch (const std::exception &e)
    {
        std::cerr << "Exception: " << e.what() << '\n';
    }

    return 0;
}

3、异步服务器测试

4、当前异步服务器存在的问题及后续优化

当前服务器存在的问题:

1) 当前服务器无法主动发送消息,知道靠收到客户端消息的回调函数来发送消息,现实中不实用。

2) 当前服务器未实现伪闭包延长CSession的生命周期,有可能写回调释放了CSession类后,读回调还会调用。

3)当前服务器未实现粘包、粘包的处理。

综上会在后续博客中优化。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/668116.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【Pytest实战】Pytest 如何生成优美的测试报告(allure-pytest)

&#x1f604;作者简介&#xff1a; 小曾同学.com,一个致力于测试开发的博主⛽️&#xff0c;主要职责&#xff1a;测试开发、CI/CD 如果文章知识点有错误的地方&#xff0c;还请大家指正&#xff0c;让我们一起学习&#xff0c;一起进步。&#x1f60a; 座右铭&#xff1a;不想…

施耐德电气:以数字化利器,助力中国产业“双转型”

近日&#xff0c;以“创新融生态&#xff0c;加速双转型”为主题的2023施耐德电气创新峰会在乌镇圆满举行。大会上&#xff0c;数千位行业专家、业界领袖和专业人士共聚一堂&#xff0c;共同探讨中国产业如何迈向“数字化”和“绿色低碳”的双转型&#xff0c;旨在为中国产业的…

SpringBoot构造流程源码分析------阶段一

SpringApplication的初始化简介 在入口类主要通过SpringApplication的静态方法–run方法进行SpringApplication类的实例化操作&#xff0c;然后再针对实例化对象调用另一个run方法完成整个项目的初始化和启动。本章节重点围绕此过程的前半部分&#xff08;即SpringApplication…

嵌入式系统开发复习指北

【嵌入式系统】20计科3-4班 第1讲 文件IO操作测试 【嵌入式系统】20计科3-4班 第2讲第4讲进程控制与线程测试 【嵌入式系统】20计科3-4班 第3讲进程通信测试 【嵌入式系统】20计科3-4班 第5-6讲内核和BootLoader开发测试 【嵌入式系统】20计科3-4班 第7讲驱动程序开发测试 大题…

PCB设计系列分享-高速ADC布局布线技巧

目录 概要 整体架构流程 技术名词解释 技术细节 1.裸露焊盘 2.最佳连接 3.去耦和层电容 4.PDS的高频层电容 5.分离接地 小结 概要 在当今的工业领域&#xff0c;系统电路板布局已成为设计本身的一个组成部分。因此&#xff0c;设计工程师必须了解影响高速信号链设计性能的机制。…

【操作系统】期末复习汇总最全版本!电子科技大学2023期末考试

操作系统 【考后感悟】本次考试考察了&#xff1a;操作系统的4大特征、线程和进程的区别、页表与页的基本地址变换机构、磁盘调度算法、银行家算法、调度算法&#xff08;短作业优先、时间片轮转&#xff09;、Linux的一些基本知识、shell读程序题以及PV操作编程。知识点基本涵…

目标检测经典工作发展(超详细对比):R-CNN vs SPPNet vs Fast R-CNN vs Faster R-CNN

序 网上关于两阶段目标检测&#xff08;two-stage object detection&#xff09;的几个经典工作R-CNN&#xff0c;SPPNet&#xff0c;Fast R-CNN&#xff0c;Faster R-CNN的发展&#xff0c;各自的优缺点缺乏一个比较清楚的描述&#xff0c;大部分文章讲的比较细节&#xff0c…

代码随想录算法训练营第四十一天| 背包问题

标准背包问题 有n件物品和一个最多能背重量为w 的背包。 第i件物品的重量是weight[i]&#xff0c;得到的价值是value[i] 。每件物品只能用一次&#xff0c;求解将哪些物品装入背包里物品价值总和最大。 举一个例子&#xff1a; 背包最大重量为4。 物品为&#xff1a; 重量价…

c++之qt学习 基本介绍 界面设计 串口

这里写目录标题 qt基类介绍qt不同版本qt下载打开qt creater制作简单qt界面ui界面点击forms&#xff0c;双击ui文件&#xff0c;就可以进入ui编辑器 qt信号和槽给界面增加图片界面布局布局不会影响代码 界面切换更改代码验证账号密码 qt的三驾马车串口助手为下拉框加入属性信息串…

力扣动态规划专题(四)劫舍问题与股票问题 打家劫舍Ⅰ Ⅱ Ⅲ 买卖股票最佳时机Ⅰ Ⅱ Ⅲ IV 步骤及C++实现

文章目录 198. 打家劫舍213. 打家劫舍 II337. 打家劫舍 III121. 买卖股票的最佳时机动态规划贪心算法 122. 买卖股票的最佳时机 II动态规划贪心算法 123.买卖股票的最佳时机III188.买卖股票的最佳时机IV309.最佳买卖股票时机含冷冻期714.买卖股票的最佳时机含手续费 198. 打家劫…

为摸鱼助力:一份Vue3的生成式ElementPlus表单组件

目录 一、实现背景 二、简介 三、组织架构设计 四、实现方式 五、代码示例 六、示例代码效果预览 七、项目预览地址 & 项目源码地址 目前项目还有诸多待完善的地方&#xff0c;大家有好的想法、建议、意见等欢迎再次评论&#xff0c;或于github提交Issues 一、实现…

杭州市等级保护测评机构名录-2023年

等级保护测评机构并不是一成不变的&#xff0c;因为有年审不符合条件被撤销的&#xff0c;也有符合条件新增的&#xff0c;所以需要不定时查看的。这里小编就给大家汇总了2023年杭州市等级保护测评机构名录。 杭州市等级保护测评机构名录-2023年 序号&#xff1a;1 机构名称…

开源SCRM营销平台MarketGo-营销通道

一、概述 互联网逐步由蓝海市场往红海市场走&#xff0c;互联网增量的红利基本到顶了。营销层面过去要获取新用户&#xff0c;现在需要考虑用户的留存、活跃、复购等&#xff0c;重心从拉新向留存用户的精细化运营转移&#xff1b;当人口红利慢慢消失&#xff0c;成本也在逐渐…

零基础学会Python编程——开发环境的搭建

作者简介&#xff1a;一名云计算网络运维人员、每天分享网络与运维的技术与干货。 座右铭&#xff1a;低头赶路&#xff0c;敬事如仪 个人主页&#xff1a;网络豆的主页​​​​​​ 目录 前言 学习目标 一.python 介绍 1.Python 的历史 2.Python 的应用领域 二.Pytho…

电源开关这个丨和0哪个在上方?

开关这个丨和0哪个在上方&#xff1f; 开关的I或O的位置&#xff0c;根据安装的方向不同而不同。一般情况下上下方向安装时&#xff0c;都是O在上面。而水平安装时则是左O右I。 开关图片 在这种类型的开关中&#xff0c;是将“|”和“O”作为一个电源开闭循环的标示&#xff0…

PtaPython练习

一、3位水仙花数计算 1、题目 3位水仙花数”是指一个三位整数&#xff0c;其各位数字的3次方和等于该数本身。例如&#xff1a;ABC是一个“3位水仙花数”&#xff0c;则&#xff1a;A的3次方&#xff0b;B的3次方&#xff0b;C的3次方 ABC。‪‬‪‬‪‬‪‬‪‬‮‬‪‬‮‬…

《面试1v1》Spring循环依赖

&#x1f345; 作者简介&#xff1a;王哥&#xff0c;CSDN2022博客总榜Top100&#x1f3c6;、博客专家&#x1f4aa; &#x1f345; 技术交流&#xff1a;定期更新Java硬核干货&#xff0c;不定期送书活动 &#x1f345; 王哥多年工作总结&#xff1a;Java学习路线总结&#xf…

Web前端 3D开发入门规划 3D效果将不再是桌面应用的专利

随着 WEB领域的快速发展 3D技术开始不再是桌面应用的专利 WEB3D技术的应用 实现了启用网址的3维呈现 让界面更直观 立体的展示 他打破了传统平面的展示形式 那么 目前的话 政府也有大量的新基建的项目 如 数字孪生 智慧城市 智慧园区 智慧工厂 智慧消费等等项目都涉及到了 3D…

系统磁盘从MBR格式转换成GPT格式来升级win11

之前的《用移动硬盘当系统盘&#xff0c;即插即用》中说到&#xff0c;需要把磁盘格式转化为MBR格式才能执行下去。问题是&#xff0c;win10升级win11要求启动方式为UEFI的话&#xff0c;磁盘格式不能为MBR。其实不升级也不影响啥&#xff0c;但是就是想好看点。所以花了点时间…

推荐系统学习

推荐系统 系统职能&#xff1a;头条/抖音/快手&#xff0c;都是以推荐系统作为流量的分发的主要手段&#xff1b; 职业发展&#xff1a;大数据处理/流式计算/数据挖掘/机器学习/高并发服务等领域。 更具用户的离十信息和行为&#xff0c;向用户推荐他感兴趣的内容 基于行为的…