boost库中优秀的网络库asio

一、须知

开发大型项目,肯定需要使用一些框架,这些框架可以由你自己亲自手工实现,也可以直接引用第三方库。

1、自己实现框架
优点:程序的所有细节都能非常清楚的掌握。
缺点:工作量大、难度高。

2、引用第三方库
优点:选择一个稳定、靠谱的第三方框架,将很大程度降低工作量、提高开发效率,将精力重点放在业务逻辑。
缺点:库本身有功能和性能问题。

因此,请尽量使用优秀的第三方库,避免重复造轮子(自己造的轮子问题频发)。

二、ASIO

asio 是boost库中优秀的网络库。asio是一个异步的io库,支持以同步或异步的方式处理事件,也可以用于基于tcp或udp的网络通信。

(1)可移植到windows、linux、FreeBSD。
(2)可扩展性。
(3)效率很高。
(4)易使用,类 Socket API 编程模型。

支持同步、异步通信方式。

三、我们将从研究同步操作开始

asio可以进行io对象(比如socket套接字)进行同步操作和异步操作。 在使用Asio之前,对Asio的各个部分、你的程序以及它们是如何一起工作的有个概念的了解是很有用的。作为一个介绍性的例子,让我们考虑一下在套接字上执行连接操作时会发生什么。
在这里插入图片描述
你的程序至少会有一个I/O执行上下文,比如asio::io_context对象,asio::thread_pool对象,或者asio::system_context。这个I/O执行上下文表示程序到操作系统I/O服务的链接。

asio::io_context io_context;

要执行I/O操作,你的程序需要一个I/O对象,比如一个TCP套接字:

asio::ip::tcp::socket socket(io_context);

当执行同步连接操作时,会发生以下事件序列:

  1. 你的程序通过调用I/O对象来启动连接操作
socket.connect(server_endpoint);
  1. I/O对象将请求转发给I/O执行上下文。

  2. I/O执行上下文调用操作系统来执行连接操作。

  3. 操作系统将操作的结果返回给I/O执行上下文。

  4. I/O执行上下文将操作产生的任何错误转换为asio::error_code类型的对象。error_code可以与特定的值进行比较,或者作为布尔值进行比较(如果结果为假,则表示没有发生错误)。然后将结果转发回I/O对象。

  5. 如果操作失败,I/O对象会抛出一个asio::system_error类型的异常。如果初始化操作的代码被写成:

asio::error_code ec;
socket.connect(server_endpoint, ec);

然后error_code变量ec将被设置为操作的结果,并且不会抛出异常。

四、当使用异步操作时,会发生不同的事件序列

在这里插入图片描述

  1. 你的程序通过调用I/O对象来初始化连接操作
socket.async_connect(server_endpoint, your_completion_handler);

其中your_completion_handler是一个带有签名的函数或函数对象:

void your_completion_handler(const asio::error_code& ec);

所需的确切签名取决于正在执行的异步操作。参考文档指出了每个操作的适当形式。

  1. I/O对象将请求转发给I/O执行上下文。

  2. I/O执行上下文向操作系统发出信号,说明它应该启动异步连接。
    在这里插入图片描述

  3. 操作系统通过将结果放置在一个队列中表示连接操作已经完成,准备由I/O执行上下文获取。

  4. 当使用io_context作为I/O执行上下文时,你的程序必须调用io_context::run()(或类似的io_context成员函数)以便检索结果。当有未完成的异步操作时,调用io_context::run()会阻塞,所以你通常会在你开始第一个异步操作时调用它。

  5. 在调用io_context::run()时,I/O执行上下文会将操作的结果从队列中取出,转换成一个error_code,然后将其传递给完成处理程序。

五、Proactor模型

在这里插入图片描述

  • 各部分内容
  1. — Asynchronous Operation (异步操作)
  • 定义一个异步执行的操作,如Socket异步读写。
  1. Asynchronous Operation Processor (异步操作执行器)
  • 执行一个异步操作,并执行完成事件队列中的队列事件,从更高层次上说,像reactive_socket_service的服务就是一个异步操作处理器。
  1. Completion Event Queue (事件完成队列)
  • 缓存完成事件直到被异步事件分离器弹出队列。
  1. Completion Handler (处理器)
  • 处理异步操作的结果,处理器是函数对象,往往使用bind创建。
  1. Asynchronous Event Demultiplexer (异步事件分离器)
  • 阻塞等待在完成事件队列中事件发生,之后向调用者返回完成事件。
  1. Proactor
  • 调用异步事件信号分离器将事件移出队列,并分配一个关联的处理器(如调用函数对象),这个功能封装在io_service类中。
  1. Initiator
  • 执行特定程序代码启动异步操作,初始化器通过如basic_stream_socket等高层次接口与异步操作处理器交互,并返回reactive_socket_service等类型的服务代理。

六、常用内容

  1. asio::io_context
  • asio提供的一个基本的io对象,只有调用其run方法的线程才会被asio调度去执行任务,可以通过post方法添加一个任务。
 asio::io_context main;
    //make_work_guard作用,创建一个executor_work_guard对象,在构造时通知io_context有任务开始,保证run方法不会退出
    //析构时相反,让run方法在没有未完成任务时退出
    auto i = aso::make_work_guard(main);
    another.post([&main]()
    {
    
    
        std::cout << "111" << std::endl;
        main.post(...)
    });

  1. 定时器asio::steady_timer
  • 一个定时器,可以使用同步和异步等待两种方式。
  void callback(const asio::error_code &error){
    
    
	    std::cout << 1 << std::endl;
    }

    asio::io_context io;
    asio::steady_timer time(io, std::chrono::seconds(3));
    time.wait();    //同步等待,定时器到时继续执行
    time.async_wait(&callback)  //异步等待,到时回调callback

  1. 信号集asio::singal_set
  • 信号集,可以注册相应信号的处理事件。
asio::signal_set signal(io, SIGINT, SIGTERM);
	signal.async_wait([&io](const asio::error_code& err, int sig) {
    
    
		io.stop();
	});

  1. Tcp通信框架
  • 服务端tcp通信需要通过acceptor接受链接,客户端需要通过resolver解析服务器端口及ip地址。
//服务器注册一个链接接收器acceptor和一个用于tcp通信的socket
    asio::ip::tcp::acceptor acceptor(io, asio::ip::tcp:endpoint(asio::ip::tcp::v4(), 5005));
    asio::ip::tcp::socket socket(io);

    //同步接受链接
    acceptor.accept(socket);
    //异步接受链接
    acceptor.async_accept(socket, &callback);

    //客户端使用resolver解析ip与端口,并注册与服务器通信的socket
    asio::ip::tcp::resolver resolver(io);
    asio::ip::tcp::socket socket(io);
    /**
     * @ param hostname
     * @ param port
     */
    asio::ip::tcp::resolver::results_type endpoints = resolver.resolve("127.0.0.1", 5005);
    asio::connect(socket, endpoints);

    //socket同步的读写,buffer对象可以接受string、array、vector
    socket.write_some(asio::buffer(msg), error);
    size_t len = socket.read_some(asio::buffer(buf), error);

    //socket异步的读写
    socket.async_write_some(asio::buffer(msg), &callback);
    socket.async_read_some(asio::buffer(buf), &callback);

  1. udp通信
  • udp无连接,因此只需用resolver解析出对端ip与端口。
//解析对端ip和端口,udp的resolver会返回一个符合名字和端口的list的迭代器
    asio::ip::udp::resolver resolver(io);
    asio::ip::udp::endpoint server_endpoint = *resolver.resolve(asio::ip::udp::v4(), "127.0.0.1", "5005").begin();
    asio::ip::udp::socket socket(io);
    socket.open(asio::ip::udp::v4());

    //服务器创建socket并绑定端口
    asio::ip::udp::socket socket(io, asio::ip::udp::endpoint(asio::ip::udp::v4(), 5005));

    //同步发送与接受数据
    socket.send_to(asio::buffer(msg), server_endpoint);
    asio::ip::udp::endpoint from_endpoint;
    size_t len = socket.receive_from(asio::buffer(buf), from_endpoint);

    //异步发送与接受
    socket.async_send_to(asio::buffer(msg), endpoint, &callback);
    socket.async_receive_from(asio::buffer(buf), from_endpoint, &callback);

test.cpp

#include <asio.hpp>



class tcpServer
{
    
    

};

int main()
{
    
    
    asio::io_context io;

}

七、C++ 建立本地网络服务器 (Boost.Asio库)

今天我们利用Boost库中Asio部分,浅尝网络服务器。此处不做过于深入的开展,为达成学习目的,只做简单的异步并发服务器。本篇代码没有直接引用boost等命名空间,为的是新入门Boost的同学能够更好的了解每个参数在boost的具体命名空间位置,有助于更好的理解boost的布局。

1.服务器用例

我们在做服务器之前,首先细想一下,服务器应具备哪些基本特质。

  1. 构建: 一个服务器应该具备被连接的IP地址(网络地址)、可以被访问的Port(端口号)。
  2. 聆听: 服务器应该能够实时处理基本的连接请求。
  3. 处理: 交互才是目的,可以与客户端实现基本的交互。
  4. 异步: 处理客户端的请求时,不会因为客户端的延迟响应而导致程序假死。

1.建造(Build)

电脑里有非常多的端口,而客户端只会把消息传到约定的地址与端口,只有在正确的端口等待,才能接到自己预期的客户。

就好像楼房里有非常多层楼一样,而快递员只会把物品送到约定的楼层,只有在正确的楼层等待,才能达成预期的结果。

#include <iostream>
#include <boost/asio.hpp>
 
int main(void) {
    
    
	try {
    
    
		std::cout << "server start." << std::endl;
		// asio程序必须的io_service对象
		boost::asio::io_service ios;
		// 具体的服务器地址与端口
		boost::asio::ip::tcp::endpoint endpotion(boost::asio::ip::tcp::v4(), 13695);
		// 创建acceptor对象,当前的IPV4作为服务器地址(127.0.0.1 || 0.0.0.0),接受端口13695的消息.
		boost::asio::ip::tcp::acceptor acceptor(ios, endpotion);
		// 打印当前服务器地址
		std::cout << "addr: " << acceptor.local_endpoint().address() << std::endl;
		// 打印当前服务器端口
		std::cout << "port: " << acceptor.local_endpoint().port() << std::endl;
	}
	catch (...) {
    
    
		std::cout << "server exceptional." << std::endl;
	}
	std::cout << "server end." << std::endl;
	getchar();
	return 0;
}

2.聆听(Listen)

一个基本的连接,在正常的情况下,应该由客户端发起,服务器应该处于实时监听的状态,因为能接到客户端发起的连接请求,这才是网络操作的根本。

#include <iostream>
#include <boost/asio.hpp>
 
int main(void) {
    
    
	try {
    
    
		std::cout << "server start." << std::endl;
		// asio程序必须的io_service对象
		boost::asio::io_service ios;
		// 具体的服务器地址与端口
		boost::asio::ip::tcp::endpoint endpotion(boost::asio::ip::tcp::v4(), 13695);
		// 创建acceptor对象,当前的IPV4作为服务器地址(127.0.0.1 || 0.0.0.0),接受端口13695的消息.
		boost::asio::ip::tcp::acceptor acceptor(ios, endpotion);
		// 打印当前服务器地址
		std::cout << "addr: " << acceptor.local_endpoint().address() << std::endl;
		// 打印当前服务器端口
		std::cout << "port: " << acceptor.local_endpoint().port() << std::endl;
 
		// 循环执行服务
		while (true) {
    
    
			// 一个临时的socket对象
			boost::asio::ip::tcp::socket socket(ios);
			// 阻塞等待客户端连接,连接成功后返回socket, accept这个函数使用引用来调取socket.
			acceptor.accept(socket);
			// 打印与本机服务器取得连接的客户端IP地址
			std::cout << "client: " << socket.remote_endpoint().address() << std::endl;
		}
	}
	catch (std::exception& _e) {
    
    
		std::cout << "server exceptional." << std::endl;
		std::cout << _e.what() << std::endl;
	}
	std::cout << "server end." << std::endl;
	getchar();
	return 0;
}

3.处理(Operation)

一旦服务器收到客户端发起的连接请求,便为客户端建立服务。与客户端建立连接的目的,始终是为了交互,我们不能本末倒置。我们尝试一下,第一次交互的滋味。

#include <iostream>
#include <boost/asio.hpp>
 
int main(void) {
    
    
	try {
    
    
		std::cout << "server start." << std::endl;
		// asio程序必须的io_service对象
		boost::asio::io_service ios;
		// 具体的服务器地址与端口
		boost::asio::ip::tcp::endpoint endpotion(boost::asio::ip::tcp::v4(), 13695);
		// 创建acceptor对象,当前的IPV4作为服务器地址(127.0.0.1 || 0.0.0.0),接受端口13695的消息.
		boost::asio::ip::tcp::acceptor acceptor(ios, endpotion);
		// 打印当前服务器地址
		std::cout << "addr: " << acceptor.local_endpoint().address() << std::endl;
		// 打印当前服务器端口
		std::cout << "port: " << acceptor.local_endpoint().port() << std::endl;
 
		// 循环执行服务
		while (true) {
    
    
			// 一个临时的socket对象
			boost::asio::ip::tcp::socket socket(ios);
			// 阻塞等待客户端连接,连接成功后返回socket, accept这个函数使用引用来调取socket.
			acceptor.accept(socket);
			// 打印与本机服务器取得连接的客户端IP地址
			std::cout << "client: " << socket.remote_endpoint().address() << std::endl;
 
 
			//处理/
			std::string msg;
			// 阻塞发送作者名称到客户端
			socket.write_some(boost::asio::buffer("hello CSND_Ayo"));
			// 阻塞接收客户端发来的数据
			socket.read_some(boost::asio::buffer(msg));
			// 打印客户端发来的数据
			std::cout << "client reply: " << msg.c_str() << std::endl;
		}
	}
	catch (std::exception& _e) {
    
    
		std::cout << "server exceptional." << std::endl;
		std::cout << _e.what() << std::endl;
	}
	std::cout << "server end." << std::endl;
	getchar();
	return 0;
}

4.异步(Async)

处理客户端的请求时,不会因为客户端的延迟响应而导致程序假死。

#include <iostream>
#include <boost/asio.hpp>
#include <boost/bind.hpp>
 
// 异步服务器类
class Server {
    
    
 
private:
 
	// 服务实例
	boost::asio::io_service& ios_;
 
	// 接收器实例
	boost::asio::ip::tcp::acceptor acceptor_;
 
	// socket智能指针
	typedef boost::shared_ptr<boost::asio::ip::tcp::socket> socket_ptr;
 
public:
 
	Server(boost::asio::io_service& _ios) : ios_(_ios),
		acceptor_(_ios, boost::asio::ip::tcp::endpoint(boost::asio::ip::tcp::v4(), 13695)) {
    
    
		// 默认执行
		start();
	}
 
	// 启动网络侦听的操作入口
	void start(void) {
    
    
		// 自定义的智能指针
		socket_ptr socket(new boost::asio::ip::tcp::socket(ios_));
		// 异步侦听,若有服务连接,则自动调用Server::handler_accept函数,并将error, socket传入作为参数
		acceptor_.async_accept(*socket,
			boost::bind(&Server::accept_handler, this,
			boost::asio::placeholders::error/* 此处作为占位符 */, socket));
	}
 
	// 请求者响应后触发的处理器
	void accept_handler(const boost::system::error_code& _ec, socket_ptr _socket) {
    
    
		// 错误码检测
		if (_ec) {
    
    
			return;
		}
		// 打印当前连接进来的客户端
		std::cout << "client: " << _socket->remote_endpoint().address() << std::endl;
		// 异步发送 "hello CSND_Ayo" 消息到客户端,发送成功后,自动调用Server::write_handler函数
		_socket->async_write_some(boost::asio::buffer("hello CSND_Ayo"),
			boost::bind(&Server::write_handler, this,
			boost::asio::placeholders::error/* 此处作为占位符 */));
		// 启动新的异步监听
		start();
	}
 
	// 完成异步写操作后的处理器
	void write_handler(const boost::system::error_code& _ec) {
    
    
		std::cout << "server: send message complete." << std::endl;
	}
 
};
 
 
 
int main(void) {
    
    
	try {
    
    
		std::cout << "server start." << std::endl;
		// 建造服务对象
		boost::asio::io_service ios;
		// 构建Server实例
		Server server(ios);
		// 启动异步调用事件处理循环
		ios.run();
	}
	catch (std::exception& _e) {
    
    
		std::cout << _e.what() << std::endl;
	}
	std::cout << "server end." << std::endl;
	return 0;
}

八、简易并发服务器类

两个类来撰写了一个并发的服务器类:Server(服务器监听类)、Session(会话类)。

具备功能:

  1. 异步监听客户端连接。
  2. 客户连接时,首包要求具有特定格式(协议包)。
  3. 并发处理客户端交互。

在这里插入图片描述
Server.h

#ifndef __CLY_SERVER_H__
#define __CLY_SERVER_H__
#include <string.h>  
#include <boost/asio.hpp>
#include <boost/shared_ptr.hpp>
class Session;
class Server {
    
    
private:
	// 会话 - 智能指针
	typedef	boost::shared_ptr<Session>	session_ptr;
public:
	Server(boost::asio::io_service &_ioService, boost::asio::ip::tcp::endpoint &_endpoint);
	virtual ~Server(void);
	// 监听
	void start(void);
	// 异步
	void run(void);
private:
	// 数据导出接口
	void callback_session(std::string _fromIp, std::string _info);
	// 会话启动
	void accept_handler(session_ptr _chatSession, const boost::system::error_code& _error);
private:
	boost::asio::io_service &ioService_;
	boost::asio::ip::tcp::acceptor acceptor_;
};
#endif // __CLY_SERVER_H__

Server.cpp

#include <boost/bind.hpp>
 
#include "Server.h"
#include "Session.h"
 
 
Server::Server(boost::asio::io_service &_ioService, boost::asio::ip::tcp::endpoint &_endpoint)
: ioService_(_ioService), acceptor_(_ioService, _endpoint) {
    
    
	start();
}
 
 
Server::~Server(void) {
    
    
}
 
void Server::start(void) {
    
    
	session_ptr	new_chat_session(new Session(ioService_));
 
	acceptor_.async_accept(new_chat_session->socket(),
		boost::bind(&Server::accept_handler, this, new_chat_session,
		boost::asio::placeholders::error));
}
 
void Server::run(void) {
    
    
	ioService_.run();
}
 
void Server::callback_session(std::string /*_fromIp*/, std::string /*_info*/) {
    
    
	return;
}
 
void Server::accept_handler(session_ptr _chatSession, const boost::system::error_code& _error) {
    
    
	if (!_error && _chatSession) {
    
    
		try {
    
    
			_chatSession->start();
			start();
		}
		catch (...) {
    
    
			return;
		}
	}
}

Session.h

#ifndef __CLY_SESSION_H__
#define __CLY_SESSION_H__
 
#include <iostream>
#include <string>
 
#include <boost/asio.hpp>
#include <boost/enable_shared_from_this.hpp>
 
#define REPLY_SIZE (32)
 
// 会话类
class Session : public boost::enable_shared_from_this<Session>
{
    
    
 
public:
 
	typedef void pSessionCallback(std::string, std::string);
 
public:
 
	Session(boost::asio::io_service& _ioService);
	virtual ~Session(void);
 
	void start(void);
 
	void setCallback(pSessionCallback* _callback) {
    
     callback_ = _callback; }
 
	// socket 实例
	boost::asio::ip::tcp::socket& socket(void);
 
private:
	
	// 第一个协议包
	void init_handler(const boost::system::error_code& _error);
 
	// 解析协议包
	void analyse_handler(const boost::system::error_code& _error);
 
	// 完成数据传输后触发的收尾工作
	void done_handler(const boost::system::error_code& _error);
 
	// 读取成功后触发的函数
	void read_handler(const boost::system::error_code& _error, size_t _readSize);
 
	// 写入完成后触发的函数
	void write_handler(const boost::system::error_code& _error);
 
private:
	// 临时信息缓冲区
	char msg_[1024];
	std::string currentMsg_;
	// 数据总数量
	int sumSize_;
	// 单个数据包大小
	unsigned int maxSize_;
	// socket句柄
	boost::asio::ip::tcp::socket socket_;
	// 回调
	pSessionCallback* callback_;
 
};
 
 
#endif // __CLY_SESSION_H__

Session.cpp

#include <boost/bind.hpp>
 
#include "Session.h"
 
 
Session::Session(boost::asio::io_service& _ioService)
:socket_(_ioService) {
    
    
	memset(msg_, 0, sizeof(msg_));
}
 
 
Session::~Session(void)
{
    
    
}
 
 
void Session::start(void) {
    
    
	// 告诉链接成功的客户端,你想要的信息。
	char msg[256] = "001:Connect Succeed! Please tell me with 10 bytes, the total data and the size of each package, example:128 1024";
	boost::asio::async_write(socket_, boost::asio::buffer(msg, strlen(msg)),
		boost::bind(&Session::init_handler, shared_from_this(),
		boost::asio::placeholders::error));
}
 
boost::asio::ip::tcp::socket& Session::socket(void) {
    
    
	return socket_;
}
 
 
// 第一个协议包
void Session::init_handler(const boost::system::error_code& _error) {
    
    
	if (_error) {
    
    
		return;
	}
	// 读取客户端发来的 10 bytes,确定单个包的大小以及数据总大小
	boost::asio::async_read(socket_, boost::asio::buffer(msg_, 10),
		boost::bind(&Session::analyse_handler, shared_from_this(),
		boost::asio::placeholders::error));
 
}
 
void Session::analyse_handler(const boost::system::error_code& _error) {
    
    
	if (_error) {
    
    
		return;
	}
	// 分析协议包格式
	bool bflag = true;
	// 正则分析格式
 
	// do something.
	if (!bflag) {
    
    
		start();
		return;
	}
 
	// 格式化保存协议包数据
	std::stringstream io(msg_);
	io >> maxSize_;
	io >> sumSize_;
 
	// 发送接收请求信息
	char msg[REPLY_SIZE];
	sprintf_s(msg, "001:is ok, data remaining %d.", sumSize_);
	boost::asio::async_write(socket_, boost::asio::buffer(msg, REPLY_SIZE),
		boost::bind(&Session::write_handler, shared_from_this(),
		boost::asio::placeholders::error));
}
 
 
// 完成数据传输
void Session::done_handler(const boost::system::error_code& _error) {
    
    
	if (_error) {
    
    
		return;
	}
	currentMsg_ += msg_;
	// 发送信息到回调
	if (!currentMsg_.empty() && callback_ != nullptr) {
    
    
		callback_(socket_.remote_endpoint().address().to_string(), currentMsg_);
		currentMsg_.clear();
	}
	memset(msg_, 0, sizeof(msg_));
 
	char msg[32] = "001:will done.";
	boost::asio::async_write(socket_, boost::asio::buffer(msg, REPLY_SIZE),
		boost::bind(&Session::init_handler, shared_from_this(),
		boost::asio::placeholders::error));
}
 
void Session::read_handler(const boost::system::error_code& _error, size_t _readSize) {
    
    
	if (_error) {
    
    
		return;
	}
	// 数据处理
	currentMsg_ += msg_;
	if (currentMsg_.size() > 1024 * 512) {
    
    
		// 发送信息到回调
		if (callback_ != nullptr) {
    
    
			callback_(socket_.remote_endpoint().address().to_string(), currentMsg_);
			currentMsg_.clear();
		}
	}
	memset(msg_, 0, sizeof(msg_));
 
	// 计算当前剩余数据数量
	sumSize_ -= _readSize;
 
	// 接收完成
	if (0 > sumSize_) {
    
    
		done_handler(_error);
	}
	// 继续接收
	else {
    
    
		char msg[REPLY_SIZE];
		sprintf_s(msg, "001:%d.", sumSize_);
		boost::asio::async_write(socket_, boost::asio::buffer(msg, REPLY_SIZE),
			boost::bind(&Session::write_handler, shared_from_this(),
			boost::asio::placeholders::error));
 
		std::cout << "send client recv succeed: " << msg << std::endl;
	}
 
 
	
}
void Session::write_handler(const boost::system::error_code& _error) {
    
    
	if (_error) {
    
    
		return;
	}
 
	boost::asio::async_read(socket_, boost::asio::buffer(msg_, maxSize_),
		boost::bind(&Session::read_handler, shared_from_this(),
		boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred));
}

main.cpp

#include <iostream>
#include <boost/asio.hpp>
#include <boost/bind.hpp>
 
#include "Server.h"
 
int main(void) {
    
    
	try {
    
    
		std::cout << "server start." << std::endl;
		// 建造服务对象
		boost::asio::io_service ios;
		// 具体的服务器地址与端口
		boost::asio::ip::tcp::endpoint endpotion(boost::asio::ip::tcp::v4(), 13695);
		// 构建Server实例
		Server server(ios, endpotion);
		// 启动异步调用事件处理循环
		server.run();
	}
	catch (std::exception& _e) {
    
    
		std::cout << _e.what() << std::endl;
	}
	std::cout << "server end." << std::endl;
	return 0;
}

总诉

这是Asio运作方式的简单介绍。 如果你的需求更高级,比如扩展Asio来执行其他类型的异步操作,你会想要更深入地研究文档。

猜你喜欢

转载自blog.csdn.net/qq_44918090/article/details/126575034