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

CPP网络编程-异步sever

代码:

// AsyncServer.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//#include <iostream>
#include<boost/asio.hpp>
#include"Session.h"int main()
{try {boost::asio::io_context ioc;using namespace std;Server s(ioc, 10086);ioc.run();}catch(std::exception& e) {std::cout << e.what() << std::endl;}
}
//Session.h
#pragma once
#include<iostream>
#include<boost/asio.hpp>using boost::asio::ip::tcp;
class Session
{
public:Session(boost::asio::io_context& ioc):_socket(ioc) {}tcp::socket& Socket() {return _socket;}void Start();private:void handle_read(const boost::system::error_code& error, size_t bytes_transferred);void handle_write(const boost::system::error_code& error);//异步发送,发送完tcp::socket _socket;enum { max_length = 1024 };char _data[max_length];
};//建立连接
class Server {
public:Server(boost::asio::io_context& ioc, short port);
private:void start_accept();void handle_accept(Session* new_session, const boost::system::error_code& error);boost::asio::io_context& _ioc;tcp::acceptor _acceptor;
};
//Session.cpp
#include "Session.h"
#include<iostream>
using namespace std;void Session::Start() {memset(_data, 0, max_length);//置0初始化_socket.async_read_some(boost::asio::buffer(_data, max_length),std::bind(&Session::handle_read, this,placeholders::_1, placeholders::_2));//_socket——>异步读,读到的数据放在_data中,当读完后,调用handle_read
}void Session::handle_read(const boost::system::error_code& error,size_t bytes_transferred ){if (!error) {cout << "server receive data is " << _data << endl;boost::asio::async_write(_socket, boost::asio::buffer(_data, bytes_transferred),std::bind(&Session::handle_write, this, placeholders::_1));}else {cout<<"read error"<<endl;delete this;}
}void Session::handle_write(const boost::system::error_code& error) {if (!error) {memset(_data,0, max_length);_socket.async_read_some(boost::asio::buffer(_data, max_length),std::bind(&Session::handle_read, this, placeholders::_1, placeholders::_2));}else {cout << "write error" << error.value()<<endl;delete this;}
}Server::Server(boost::asio::io_context& ioc, short port):_ioc(ioc),_acceptor(ioc,tcp::endpoint(tcp::v4(),port)) {cout << "server start,port:" <<port<< endl;start_accept();
}
void Server::start_accept() {/*先创建一个new_session,然后调用async_accept,当有新的连接时,会调用handle_accept,*/Session* new_session = new Session(_ioc);_acceptor.async_accept(new_session->Socket(),std::bind(&Server::handle_accept,this,new_session,placeholders::_1));
}
void Server::handle_accept(Session* new_session, const boost::system::error_code& error) {if (!error) {new_session->Start();}else {delete new_session;}start_accept();
}

Session.h

Session 类

成员

作用
_socket与客户端通信的 TCP 套接字
_data缓冲区,最多存 1024 字节数据
Socket()返回 socket 引用,供 acceptor 使用
Start()启动异步读操作
handle_read读完成后的回调函数
handle_write写完成后的回调函数

Server 类

成员作用
_ioc引用外部 io_context
_acceptor监听指定端口的 TCP 接收器
start_accept()主动发起异步接受连接请求
handle_accept()接受连接完成后的回调

Session.cpp

void Session::Start() {memset(_data, 0, max_length);_socket.async_read_some(boost::asio::buffer(_data, max_length),std::bind(&Session::handle_read, this, placeholders::_1, placeholders::_2));
}

启动对当前socket的异步读取,等待客户端发送数据
async_read_some非阻塞读,只要有数据就触发回调,_data缓冲区,然后绑定回调函数handle_read

此函数只调用一次(在连接建立后),之后通过 handle_read → handle_write → 再次 async_read_some 形成循环。

void Session::handle_read(const boost::system::error_code& error, size_t bytes_transferred) {if (!error) {cout << "server receive data is " << _data << endl;boost::asio::async_write(_socket, boost::asio::buffer(_data, bytes_transferred),std::bind(&Session::handle_write, this, placeholders::_1));} else {cout << "read error" << endl;delete this;}
}

如果读取成功打印数据,使用async_write将数据完整回传给客户端,发送完调用handle_write

void Session::handle_write(const boost::system::error_code& error) {if (!error) {memset(_data, 0, max_length);_socket.async_read_some(boost::asio::buffer(_data, max_length),std::bind(&Session::handle_read, this, placeholders::_1, placeholders::_2));} else {cout << "write error" << error.value() << endl;delete this;}
}
  • 写操作完成后的回调。
  • 若成功:清空缓冲区,重新开始 async_read_some,等待下一条消息
Server::Server(boost::asio::io_context& ioc, short port): _ioc(ioc), _acceptor(ioc, tcp::endpoint(tcp::v4(), port)) {cout << "server start,port:" << port << endl;start_accept();
}

初始化 _acceptor,绑定到 IPv4

void Server::start_accept() {Session* new_session = new Session(_ioc);_acceptor.async_accept(new_session->Socket(),std::bind(&Server::handle_accept, this, new_session, placeholders::_1));
}
  • 每次调用都 new 一个 Session
  • 将 Session 的 _socket 作为参数传给 async_accept
  • 设置回调为 handle_accept,并把 new_session 指针传进去
void Server::handle_accept(Session* new_session, const boost::system::error_code& error) {if (!error) {new_session->Start();  // 启动会话} else {delete new_session;    // 接受失败,清理}start_accept();  // 无论成功与否,继续监听下一个连接
}
  • 如果接受连接成功 → 启动 Session::Start() 开始读取;
  • 如果失败(如监听关闭)→ 删除刚创建的 Session
                     +------------------+|   Server启动     |+--------+---------+|v创建_acceptor,绑定端口10086|v调用 start_accept()|vnew Session(_ioc)     ← 堆上创建|v_acceptor.async_accept(socket, handle_accept)|| (等待客户端连接)↓[客户端连接到来]|v触发 handle_accept()|+-------+--------+| 是否出错?     |+-------+--------+|是 /        \ 否v          vdelete session   new_session->Start()|v_socket.async_read_some(...)|| (等待客户端发数据)↓[客户端发送数据]|v触发 handle_read(...)|v打印数据 → async_write(...)|| (等待发送完成)↓触发 handle_write(...)|v清空缓冲 → 再次 async_read_some(...)|(循环往复)

http://www.xdnf.cn/news/1252639.html

相关文章:

  • 《爬虫实战指南:轻松获取店铺详情,开启数据挖掘之旅》
  • 机器学习-LinearRegression
  • 【20205CVPR-目标检测方向】基于事件的高效目标检测:具有空间和时间注意力的混合神经网络
  • QT----QAxObject在子线程中调用,发现excel指针为空
  • Kubesphere搜索镜像问题
  • Packets Frames 数据包和帧
  • SQL120 贷款情况
  • 利用C++11和泛型编程改进原型模式
  • .Net下载共享文件夹中的文件
  • Java Stream API 详解(Java 8+)
  • Linux---第二天---基础指令
  • 快速莫比乌斯变换(FMT)与莫比乌斯反演 例题:树上lcm
  • SELinux 安全机制详解与管理
  • 组合期权:跨式策略
  • 批量提问程序开发方案:基于Python的百度文小言接口实现
  • 基于 Jenkins Pipeline 实现 DITA 文档自动化构建与发布(开源方案)
  • 百度智能云给“数字人”发工牌
  • Boosting 知识点整理:调参技巧、可解释性工具与实战案例
  • Bug 记录:SecureRandom.getInstanceStrong()导致验证码获取阻塞
  • 【motion】标签体系设计与检索 1:HumanML3D 和 KIT Motion-Language(KITML)
  • Java 使用动态代理和反射实现字段变更跟踪
  • 生成网站sitemap.xml地图教程
  • 【STM32U385RG 测评】基于VSCode的STM32开发环境搭建
  • 西门子PLC基础指令6:读取时钟指令、设置时钟指令、使能含义与注意
  • 【32】C++实战篇—— m行n列的坐标点,求每行相邻点X差值dX,每列相邻点y差值dY,并以矩阵形式左端对齐
  • JAVA--流程控制语句
  • 【VS + Qt】VS2022 Qt 开发中 ui_xx.h 文件编辑报错但编译正常的问题解决
  • 「iOS」————单例与代理
  • 如何解决pip安装报错ModuleNotFoundError: No module named ‘caffe’问题
  • 河南萌新联赛2025第四场-河南大学