【问题标题】:Run threads with boost and asio使用 boost 和 asio 运行线程
【发布时间】:2015-07-24 15:38:02
【问题描述】:

简介

我正在尝试创建一个线程来接收来自套接字的数据。

代码

void ClientTcp::read_handler(tcp::socket s){
    for(;;){
        char buffer[max_buffr];
        boost::system::error_code error;
        size_t length = s.read_some(boost::asio::buffer(buffer), error);
        if (error == boost::asio::error::eof)
            break; // Connection closed cleanly by peer.
        else if (error)
            throw boost::system::system_error(error); // Some other error.
        buffer[length] = '\0';
        std::cout << "-> " << buffer << std::endl;
    }
}

void ClientTcp::run(){
    tcp::socket s(io_service_);
    tcp::resolver resolver(io_service_);
    boost::asio::connect(s, resolver.resolve({ip_, port_}));

    boost::thread read_th(read_handler, std::move(s));
    std::string message;
    for(;;){
        std::cin >> message;
        boost::asio::write(s, boost::asio::buffer(message, message.size()));
    }
    read_th.join();
}

问题

boost::thread read_th(read_handler, std::move(s)); 这一行有一个我无法理解的错误。

错误 no matching function for call to boost::thread::thread(<unresolved overloaded function type, std::remove_reference<boost::asio::basic_stream_socket<boost::asio::ip::tcp>&>::type)

主要问题 如何从类方法启动线程?

【问题讨论】:

    标签: c++ c++11 boost boost-asio


    【解决方案1】:

    回答错误的问题:你会使用boost::bind

    boost::thread read_th(boost::bind(&ClientTcp::read_handler, this, std::move(s)));
    

    但你当然不想这样做。每个异步操作都使用一个线程根本不起作用。

    Boost 让您无需额外线程即可实现异步。只需使用 async_* 函数而不是您的函数 重新使用:

    • async_read_some
    • async_write

    别忘了运行io_service::run()

    【讨论】:

    • 不行,error: use of deleted function ‘boost::asio::basic_stream_socket&lt;boost::asio::ip::tcp&gt;::basic_stream_socket(const boost::asio::basic_stream_socket&lt;boost::asio::ip::tcp&gt;&amp;)’|我会尝试异步方法。
    • 好吧。这只是意味着s 也不能移动。使用boost::ref、指针、成员等:)
    • 有效!谢谢,只需使用boost::ref 示例更新您的答案即可。
    • 别忘了“但你肯定不想那样做”部分。在您的示例中,您有 Undefined Behaviour,因为 socket is not thread safe
    • @IgorR。您只需在读取处理程序中使用tcp::socket&amp; 并从中移出。
    【解决方案2】:

    似乎boost::thread 构造函数无法对其参数执行“完美转发”(并且您不能使用bind,原因在@sehe 的cmets 中描述)。

    但是,作为 C++11 的一部分,std::thread 确实正确地转发了参数,因此编译如下:

    #include <boost/asio.hpp>
    #include <thread>
    
    using namespace boost::asio;
    
    void read_handler(ip::tcp::socket && s)
    {
    } 
    
    int main()
    {
        io_service io;
        ip::tcp::socket s(io);
        std::thread read_th(read_handler, std::move(s));
    }
    

    请注意,如果read_handler 是非静态成员函数(如您的问题中所示),则应将其与对象实例绑定:std::thread(&amp;ClientTcp::read_handler, this, std::move(s));

    (当然要考虑对象的寿命,还有@sehe提出的设计考虑。)

    【讨论】:

      猜你喜欢
      • 2016-01-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-08-26
      • 1970-01-01
      • 2017-09-02
      相关资源
      最近更新 更多