CPP网络编程-异步sever

发布于:2025-08-08 ⋅ 阅读:(20) ⋅ 点赞:(0)

代码:

// 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()
                              |
                              v
                   new Session(_ioc)     ← 堆上创建
                              |
                              v
            _acceptor.async_accept(socket, handle_accept)
                              |
                              | (等待客户端连接)
                              ↓
                  [客户端连接到来]
                              |
                              v
                   触发 handle_accept()
                              |
                      +-------+--------+
                      | 是否出错?     |
                      +-------+--------+
                              |
                   是 /        \ 否
                     v          v
               delete session   new_session->Start()
                                  |
                                  v
                     _socket.async_read_some(...)
                                  |
                                  | (等待客户端发数据)
                                  ↓
                         [客户端发送数据]
                                  |
                                  v
                       触发 handle_read(...)
                                  |
                                  v
                    打印数据 → async_write(...)
                                  |
                                  | (等待发送完成)
                                  ↓
                       触发 handle_write(...)
                                  |
                                  v
                    清空缓冲 → 再次 async_read_some(...)
                                  |
                              (循环往复)


网站公告

今日签到

点亮在社区的每一天
去签到