【发布时间】:2013-07-16 22:49:17
【问题描述】:
我正在探索使用 boost::asio 和 C++11 功能。特别是,我关注的是一个名为“async_tcp_echo_server.cpp”的示例,位于此处(代码也显示在我的问题末尾):
我的问题涉及server 类的tcp::socket 成员socket_。在server 类的do_accept() 方法中,socket_ 被传递给async_accept()。 (根据 asio 文档,async_accept() 需要 socket 作为其第一个参数来接受连接。)到目前为止,一切都很好。
下一个参数,异步接受操作的回调,是一个 lambda 函数。 lambda 的主体构造了一个新的session 对象,其构造函数也需要相同的socket。有趣的是,socket 对象不能被复制;所以在示例中,socket_ 对象是server 对象的成员,它使用std::move() 传递。
我了解“唯一”socket_ 对象(它是server 对象的“永久”成员)被“移动”到session 对象中。很好——socket 对象没有被复制,而是被移动了——每个人都很高兴。
但是在下一次调用async_accept() 时会发生什么?之前搬家的socket_(server的成员)是不是又传进来了?当我们“移动”一个成员时,留下了什么?有无限socket对象的魔法喷泉吗?
或者这里发生的事情真的不太明显?当socket 移动到session 时,是“留下/移出”对象的内容(socket_ 的成员server)交换与“新”session 对象自己的“尚未构建”socket_ 成员?我说得有道理吗?
总结
代码如下。程序流程相当简单。 main() 构造单个 server 对象。 server 反复调用async_accept()。每个async_accept() 回调创建一个新的session 对象,每个都用一个(新鲜的?)socket 构造。如果它们只是(重复地)从(单个)server 中的同一 socket_ 成员“移动”,那么所有“新鲜”socket 对象来自哪里?
#include <cstdlib>
#include <iostream>
#include <memory>
#include <utility>
#include <boost/asio.hpp>
using boost::asio::ip::tcp;
class session
: public std::enable_shared_from_this<session>
{
public:
session( tcp::socket socket )
: socket_( std::move( socket ) )
{}
void start() {
do_read();
}
private:
void do_read() {
auto self( shared_from_this() );
socket_.async_read_some(
boost::asio::buffer( data_, max_length ),
[this, self]( boost::system::error_code ec, std::size_t length )
{
if( !ec ) {
do_write( length );
}
}
);
}
void do_write( std::size_t length ) {
auto self( shared_from_this() );
boost::asio::async_write(
socket_,
boost::asio::buffer( data_, length ),
[this, self]( boost::system::error_code ec, std::size_t /*length*/ )
{
if( !ec ) {
do_read();
}
}
);
}
tcp::socket socket_;
enum { max_length = 1024 };
char data_[max_length];
};
class server {
public:
server( boost::asio::io_service& io_service, short port )
: acceptor_( io_service, tcp::endpoint( tcp::v4(), port ) )
, socket_( io_service )
{
do_accept();
}
private:
void do_accept() {
acceptor_.async_accept(
socket_,
[this]( boost::system::error_code ec )
{
if( !ec ) {
std::make_shared<session>( std::move( socket_ ) )->start(); // is this a *swap* of socket_ ???
}
do_accept();
}
);
}
tcp::acceptor acceptor_;
tcp::socket socket_;
};
int main( int argc, char* argv[] ) {
try {
if( argc != 2 ) {
std::cerr << "Usage: async_tcp_echo_server <port>\n";
return 1;
}
boost::asio::io_service io_service;
server s( io_service, std::atoi( argv[1] ) );
io_service.run();
} catch( std::exception& e ) {
std::cerr << "Exception: " << e.what() << "\n";
}
return 0;
}
【问题讨论】:
标签: boost c++11 boost-asio move move-semantics