Asio官方文档 的非官方中文翻译 (Tutorial-1-2)

自己翻译的, 没有任何参考价值

Daytime.3 - An asynchronous TCP daytime server
https://www.boost.org/doc/libs/1_74_0/doc/html/boost_asio/tutorial/tutdaytime3.html


Daytime.3 - An asynchronous TCP daytime server

注:以下代码均在 using boost::asio::ip::tcp;下

main() 函数

int main()
{
	try
	{

我们得搞一个sever对象来接收客户端连过来的连接.io_context对象提供了一些I/O服务,其中就包括待会儿要用到的socket.

		boost::asio::io_context io_context;
		tcp_server server(io_context);

打开io_context.run()来让我们把自己设的异步操作给整起来.

		io_context.run();
	}
	catch (std::exception& e)
	{
		std::cerr << e.what() << std::endl;
	}

	return 0;
}

tcp_sever类

class tcp_server
{
public:

构造函数初始化了一个acceptor,在13端口上监听TCP连接.

	tcp_server(boost::asio::io_context& io_context)
		: io_context_(io_context), 
		  acceptor_(io_context, tcp::endpoint(tcp::v4(), 13))
	{
		start_accept();
	}

private:

start_accept()函数创建了一个socket,并初始化了一个异步接受请求操作等待新连接.

	void start_accept()
	{
		tcp_connection::pointer new_connection =
			tcp_connection::create(io_context_);

		acceptor_.async_accept(new_connection->socket(), 
			boost::bind(&tcp_server::handle_accept, 
				this, 
				new_connection, 
				boost::asio::placeholders::error));
	}

当start_accept里的异步请求结束时,函数handle_accept()就被触发.它会回复来自客户端的请求,然后它又会继续调用start_accept()来初始化下一个请求操作.

	void handle_accept(tcp_connection::pointer new_connection, 
		const boost::system::error_code& error)
	{
		if (!error)
		{
			new_connection->start();
		}
		
		start_accept();
	}
	
	boost::asio::io_context& io_context_;
	tcp::acceptor acceptor_;
};

tcp_connection类

因为想让tcp_connection的对象在用到的时候一直保持存活,我们用了shared_ptr 和 enable_shared_from_this.

class tcp_connection
	: public boost::enable_shared_from_this<tcp_connection>
{
public:
	typedef boost::shared_ptr<tcp_connection> pointer;

	static pointer create(boost::asio::io_context& io_context)
	{
		return pointer(new tcp_connection(io_context));
	}

	tcp::socket& socket()
	{
		return socket_;
	}

在start()这个函数中,我们用boost::asio::async_write()来写数据给客户端.要注意这里用的是boost::asio::async_write()而不是ip::tcp::socket::async_write_some(),是为了保证发送整个数据块.

	void start()
	{

要发送的数据被存在成员变量 message_里,因为我们要保证数据在整个异步操作期间都有效.

		message_ = make_daytime_string();

在初始化异步操作的时候,如果使用了boost::bind(),那你只能转成跟人家相匹配的参数表.但是此处有两个占位符(boost::asio::placeholders::error 和 boost::asio::placeholders::bytes_transferred)其实实际上是被丢弃的,因为handle_write()根本就没有用到.

		boost::asio::async_write(socket_, boost::asio::buffer(message_), 
			boost::bind(&tcp_connection::handle_write, 
				shared_from_this(), 
				boost::asio::placeholders::error, 
				boost::asio::placeholders::bytes_transferred));

此客户端连接的任何进一步操作现在由handle_write()负责.

	}

private:
	tcp_connection(boost::asio::io_context& io_ccontext)
		: socket_(io_context)
	{
	}
	
	void handle_write(const boost::system::error_code& /*error*/, 
		size_t /*bytes_transferred*/)
	{
	}

	tcp::socket socket_;
	std::string message_;
};

整体回顾一下代码 这次的比较长而且有的地方不全

#include <ctime>
#include <iostream>
#include <string>
#include <boost/bind/bind.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/enable_shared_from_this.hpp>
#include <boost/asio.hpp>

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

std::string make_daytime_string()
{
	using namespace std;
	time_t now = time(0);
	return ctime(&now);
}

class tcp_connection
	: public boost::enable_shared_from_this<tcp_connection>
{
public:
	typedef boost::shared_ptr<tcp_connection> pointer;

	static pointer create(boost::asio::io_context& io_context)
	{
		return pointer(new tcp_connection(io_contect));
	}

	// 返回自己管理的socket对象
	tcp::socket& socket()
	{
		return socket_;
	}

	void start()
	{
		message_ = make_daytime_string();
		// 把message_里的东西写给socket_
		boost::asio::async_write(socket_, boost::asio::buffer(message_), 
			boost::bind(&tcp_connection::handle_write, 
				shared_from_this(), 
				boost::asio::placeholders::error, 
				boost::asio::placeholders::bytes_transferred));
	}

private:
	tcp_connection(bosst::asio::io_context& io_context)
		: socket_(io_context)
	{
	}

	void handle_write(const boost::system::error_code& /*error*/, 
		size_t /*bytes_transferred*/)
	{
	}
	
	tcp::socket socket_;
	std::string message_;
};

class tcp_server
{
public:
	tcp_server(boost::asio::io_context& io_context)
		: io_context_(io_context),
		  acceptor_(io_context, tcp::endpoint(tcp::v4(), 13))
  	{
  		start_accept();
  	}

private:
	void start_accept()
	{
		// 新建一个tcp连接对象
		tcp_connection::pointer new_connection = 
			tcp_connection::create(io_context_);
		
		// 安排新连接的socket()函数 等办妥了通知本对象的handle_accept()
		acceptor_.async_accept(new_connection->socket(),
			boost::bind(&tcp_server::handle_accept, 
				this,
				new_connection,
				boost::asio::placeholders::error));
	}

	void handle_accept(tcp_connection::pointer new_connection, 
		const boost::system::error_code& error)
	{
		if (!error)
		{
			new_connection->start();
		}

		start_accept();
	}

	boost::asio::io_context& io_context_;
	tcp::acceptor acceptor_;
};

int main()
{
	try
	{
		boost::asio::io_context io_context;
		tcp_server server(io_context);
		io_context.run();
	}
	catch (std::exception& e)
	{
		std::cerr << e.what() << std::endl;
	}

	return 0;
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值