在C+;中的boost::asio套接字对象上重复std::move+;11
我正在探索使用boost::asio和C++11特性。特别是,我将重点放在一个名为“async_tcp_echo_server.cpp”的示例上,该示例位于此处(问题末尾还显示了代码): 我的问题涉及在C+;中的boost::asio套接字对象上重复std::move+;11,boost,c++11,boost-asio,move,move-semantics,Boost,C++11,Boost Asio,Move,Move Semantics,我正在探索使用boost::asio和C++11特性。特别是,我将重点放在一个名为“async_tcp_echo_server.cpp”的示例上,该示例位于此处(问题末尾还显示了代码): 我的问题涉及server类的tcp::socket成员socket。在server类的do\u accept()方法中,socket被传递给async\u accept()。(根据asio文档,async_accept()要求将接受连接的socket作为其第一个参数。)到目前为止,一切正常 下一个参数,异步接
server
类的tcp::socket
成员socket
。在server
类的do\u accept()
方法中,socket
被传递给async\u accept()
。(根据asio文档,async_accept()
要求将接受连接的socket
作为其第一个参数。)到目前为止,一切正常
下一个参数,异步接受操作的回调,是一个lambda函数。lambda的主体构造了一个新的会话
对象,其构造函数也需要相同的套接字
。有趣的是,socket
对象无法复制;因此,在本例中,使用std::move()
传递socket\uuu
对象,该对象是服务器
对象的成员
我知道“唯一的”socket\uuu
对象(是服务器
对象的“永久”成员)已“移动”到会话
对象中。很好--socket
对象不是复制的,而是移动的--每个人都很高兴
但是下次调用async\u accept()
时会发生什么?先前移动的套接字
(服务器的成员)是否再次传入?当我们“移动”一个成员时,会留下什么?是否有无限的socket
对象的神奇喷泉
还是这里真的发生了一些不太明显的事情?当套接字
被移动到会话
中时,对象(服务器
的套接字
成员)的“遗留/移动”内容是否与“新的”会话
对象自己的“尚未构建”套接字
成员的内容交换?我说得通吗
总结
代码如下。程序流程相当简单main()
构造一个server
对象。服务器反复调用async\u accept()
。每个async\u accept()
回调都会创建一个新的会话
对象,每个对象都由一个(新的?套接字
构造。如果所有的“新的”socket
对象只是从(单个)服务器中的同一socket\uu
成员(重复)“移动”过来,那么它们从哪里来
#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::asio::ip::tcp;
课堂
:public std::从\u中启用\u共享\u
{
公众:
会话(tcp::套接字)
:插座(标准::移动(插座))
{}
void start(){
你读过吗;
}
私人:
void do_read(){
自动自我(从_this()共享_);
套接字异步读取(
boost::asio::buffer(数据长度,最大长度),
[this,self](boost::system::error\u code ec,std::size\u t length)
{
如果(!ec){
不写(长度);
}
}
);
}
无效写入(标准::大小\u t长度){
自动自我(从_this()共享_);
boost::asio::异步写入(
插座,
boost::asio::buffer(数据,长度),
[this,self](boost::system::error\u code ec,std::size\u t/*length*/)
{
如果(!ec){
你读过吗;
}
}
);
}
tcp::socket-socket;
枚举{max_length=1024};
字符数据[最大长度];
};
类服务器{
公众:
服务器(boost::asio::io_服务和io_服务,短端口)
:接受者(io_服务,tcp::端点(tcp::v4(),端口))
,套接字(io_服务)
{
你接受吗;
}
私人:
无效不接受{
接受方\异步\接受方(
插座,
[this](boost::system::error_code ec)
{
如果(!ec){
std::make_shared(std::move(socket_u))->start();//这是socket_uu的交换吗???
}
你接受吗;
}
);
}
tcp::接受者接受者;
tcp::socket-socket;
};
int main(int argc,char*argv[]){
试一试{
如果(argc!=2){
标准::cerr如以下文件所述:
移动后,从对象移动的对象处于与
使用基本流套接字(io_服务&)构造函数构造
上面的意思是,您可以根据需要将原始的套接字
对象从服务器
移动到会话
。移动语义可以被认为是传递资源的所有权。资源获取是实例化(RAII)是在对象构造时分配资源的所有权并在销毁时释放这些资源的概念。移动语义允许在除构造和销毁之外的其他时间转移资源的所有权
在这种情况下,对象(server::socket
)是从server::acceptor
转移OS套接字资源所有权的接收者。该转移发生在async\u accept()之后的某个时间点
在客户端连接时返回。新连接的套接字资源被移动到socket\u
中,并调用回调lambda函数。在lambda过程中,套接字资源被移动到会话::socket\u
。服务器::socket\uuu。仅在几分之一微秒的时间内拥有该资源
移动语义允许RAII类在不拥有任何资源的暮色状态下存在。考虑调用release后的unique\u ptr
(它表示没有内存)。移出后的server::socket仍然有空间容纳资源,但是