代码:
// 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(...)
|
(循环往复)