反复的std ::上的boost :: ASIO Socket对象在C ++ 11移动 [英] Repeated std::move on an boost::asio socket object in C++11

查看:183
本文介绍了反复的std ::上的boost :: ASIO Socket对象在C ++ 11移动的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用boost ::与C ++ 11的特性以及ASIO探索。特别是,我专注于所谓的async_tcp_echo_server.cpp为例,设在这里(code也是在我的问题的最后面):

<一个href=\"http://www.boost.org/doc/libs/1_54_0/doc/html/boost_asio/example/cpp11/echo/async_tcp_echo_server.cpp\">http://www.boost.org/doc/libs/1_54_0/doc/html/boost_asio/example/cpp11/echo/async_tcp_echo_server.cpp

我的问题涉及到 TCP ::插座成员插座_ 的服务器类。在 do_accept()服务器类的方法,插座_ 传递给 async_accept()。 (据ASIO文档, async_accept()要求,作为第一个参数,在插座来接受连接成)。到目前为止,一切都很好。

下一个参数,回调的异步接收操作,是一个lambda函数。拉姆达的身体构造一个新的会议的对象,它的构造也需要同样的插座。有趣的是,插座对象不能被复制;因此在本例中,插座_ 对象,这是服务器对象的成员,使用<$ C传递$ C>的std ::移动()。

据我所知,有且仅有插座_ 对象(这是的永久成员服务器对象)被​​搬到会议对象。精 - 插座对象是不可复制的,但移动 - 皆大欢喜

但在下次调用 async_accept会发生什么()?是同一个插座_ 服务器的成员),这是previously移动,再次通过呢?当我们动的一员,是什么留下什么呢?有无限的插座的神奇喷泉对象?

或者是一些真正低于明显的发生在这里?当插座移动到会议,是对内容对象(留守从/移动插座_ 服务器成员)的的与新<$ C $的内容C>会议对象自己还未构建插座_ 会员?难道我连说的吗?

摘要

code如下。程序流程相当简单。 的main()构建一个服务器对象。在服务器使得重复 async_accept电话()。每个 async_accept()回调创建一个新的会议对象,每一个(新的?)插槽。在哪里所有的新鲜插座对象来自,如果他们只是(反复)来自同一插座_ 成员(单个)服务器

 的#include&LT; cstdlib&GT;
#包括LT&;&iostream的GT;
#包括LT&;内存和GT;
#包括LT&;实用&GT;
#包括LT&;升压/ asio.hpp&GT;使用boost ::支持ASIO ::知识产权:: TCP;堂课
:公众的std :: enable_shared_from_this&LT;会议&GT;
{
上市:
    会话(TCP ::插座插座)
    :socket_(性病::移动(插座))
    {}    无效的start(){
        do_read();
    }私人的:
    无效do_read(){
        自动自我(shared_from_this());
        socket_.async_read_some(
            提高:: ASIO ::缓​​冲区(data_中的数据,MAX_LENGTH)
            [本,个体经营](升压::系统::错误_ code EC,性病::为size_t长度)
            {
                如果(!EC){
                    do_write(长);
                }
            }
        );
    }    无效do_write(的std ::为size_t长度){
        自动自我(shared_from_this());
        提高:: ASIO :: async_write(
            插座_,
            提高:: ASIO ::缓​​冲区(data_中的数据,长度)
            [本,个体经营](升压::系统::错误_ code EC,性病::为size_t / *长* /)
            {
                如果(!EC){
                    do_read();
                }
            }
        );
    }    TCP ::插座socket_;
    枚举{MAX_LENGTH = 1024};
    烧焦data_中的数据[MAX_LENGTH]
};
级服务器{
上市:
    服务器(提高:: ASIO :: io_service对象和放大器; io_service对象,短端口)
    :acceptor_(io_service对象,TCP ::端点(TCP :: V4(),口))
    ,socket_(io_service对象)
    {
        do_accept();
    }私人的:
    无效do_accept(){
        acceptor_.async_accept(
            插座_,
            [这](升压::系统::错误_ code EC)
            {
               如果(!EC){
                   的std :: make_shared&LT;会议&GT;(的std ::移动(socket_)) - &GT;启动(); //这是一个socket_ * *互换?
               }               do_accept();
            }
        );
    }    TCP ::受acceptor_;
    TCP ::插座socket_;
};
INT主(INT ARGC,CHAR *的argv []){
    尝试{
        如果(的argc!= 2){
            的std :: CERR&LT;&LT; 用法:async_tcp_echo_server&LT;港口&GT; \\ N的;
            返回1;
        }        提高:: ASIO :: io_service对象io_service对象;        服务器S(io_service对象,性病::与atoi(ARGV [1]));        io_service.run();    }赶上(的std ::例外急症){
        的std :: CERR&LT;&LT; 例外:&LT;&LT; e.what()&所述;&下; \\ n;
    }    返回0;
}


解决方案

作为<一个记录href=\"http://www.boost.org/doc/libs/1_54_0/doc/html/boost_asio/reference/basic_stream_socket/basic_stream_socket/overload5.html\"><$c$c>tcp::socket参考:


  

继移动,移动的,从对象处于相同的状态,如果
  使用basic_stream_socket(io_service对象和放大器;)构成。构造


以上意味着你可以移动服务器的原始插座对象会议多次,因为你需要。

I am exploring using boost::asio along with C++11 features. In particular, I am focusing on an example called "async_tcp_echo_server.cpp", located here (code is also shown at the end of my question):

http://www.boost.org/doc/libs/1_54_0/doc/html/boost_asio/example/cpp11/echo/async_tcp_echo_server.cpp

My question involves the tcp::socket member socket_ of the server class. In the do_accept() method of the server class, socket_ is passed to async_accept(). (According to the asio documentation, async_accept() requires, as its first parameter, the socket to accept the connection into.) So far, so good.

The next parameter, the callback for the asynchronous accept operation, is a lambda function. The body of the lambda constructs a new session object, whose constructor also needs the same socket. Interestingly, socket objects cannot be copied; so in the example, the socket_ object, which is a member of the server object, is passed using std::move().

I understand that the "one and only" socket_ object (which is a "permanent" member of the server object) is "moved" into the session object. Fine -- socket object is not copied, but moved -- everybody's happy.

But what happens on the next call to async_accept()? Is the same socket_ (member of server), that was previously moved, passed in again? When we "move" a member, what is left behind? Is there a magical fountain of unlimited socket objects?

Or is something really less-than-obvious happening here? When the socket is moved into the session, is the contents of the "left behind/moved from" object (socket_ member of server) swapped with the contents of the "new" session object's own "not-yet-constructed" socket_ member? Am I even making sense?

Summary

Code is below. Program flow is fairly simple. main() constructs a single server object. The server makes repeated calls to async_accept(). Each async_accept() callback creates a new session object, each constructed with a (fresh?) socket. Where do all the "fresh" socket objects come from, if they are simply (repeatedly) "moved" from the same socket_ member in the (single) server?

#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;
} 

解决方案

As documented in tcp::socket reference:

Following the move, the moved-from object is in the same state as if constructed using the basic_stream_socket(io_service&) constructor.

The above means that you can move the original socket object from server to session as many times as you need.

这篇关于反复的std ::上的boost :: ASIO Socket对象在C ++ 11移动的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆