传递boost::asio::ip::tcp::socket

6

好的,这是我目前的代码片段:

namespace bai = boost::asio::ip;
bai::tcp::socket tcp_connect(std::string hostname, std::string port) {
    try {
        boost::asio::io_service io_service;
        bai::tcp::resolver resolver(io_service);

        // we now try to get a list of endpoints to the server 
        bai::tcp::resolver::query query(hostname, port);
        bai::tcp::resolver::iterator endpoint_iterator = resolver.resolve(query);
        bai::tcp::resolver::iterator end;

        // looking for a successful endpoint connection
        bai::tcp::socket socket(io_service);
        boost::system::error_code error = boost::asio::error::host_not_found;
        while (error && endpoint_iterator != end) {
            socket.close();
            socket.connect(*endpoint_iterator++ , error);
        }

        if (error) throw boost::system::system_error(error);

        return socket;
    } catch (std::exception &ex) {
        std::cout << "Exception: " << ex.what() << "\n";
    }
}

我希望返回一个连接到hostnameport上的boost::asio::ip::tcp::socket。但是,我遇到了大量难以理解的boost::noncopyable错误。我的问题是,我应该如何传递这些套接字?这种做法有什么问题吗?

2个回答

15

socket 不能被复制。使用 boost::shared_ptr<bai::tcp::socket> 替代。如果你可以复制一个 socket,那么如果你最终得到两个表示相同底层 OS socket 的 socket 实例,将会引起各种有趣的问题 - 因此不允许复制(因此不允许返回值或传递值)。


我以前从未使用过 share_ptr,像这样吗?boost::shared_ptr<bai::tcp::socket*> tcp_connect(std::string hostname, std::string port) - orlp
boost::shared_ptr<bai::tcp::socket> tcp_connect(....) 然后 boost::shared_ptr<bai::tcp::socket> socket(new bai::tcp::socket(io_service)); - Erik
好的,这样可以。这意味着我需要将每个 socket.some_method() 的实例更改为 (*socket).some_method(),对吗? - orlp
1
有趣的是,有人知道为什么文档建议socket具有构造函数,可以允许这种操作吗?(请参见http://www.boost.org/doc/libs/1_47_0/doc/html/boost_asio/reference/basic_stream_socket/basic_stream_socket.html中描述的最后一个覆盖)。作为一名初学者C++程序员,我不确定我是否理解了移动构造和复制构造之间的区别 - 我认为区别在于原始对象在移动构造操作中将无法使用? - Jules
@Jules 您是正确的,但即使16个月前的票已经关闭,看起来这仍然是一个问题。https://dev59.com/tHTYa4cB1Zd3GeqP1P5I#19193337 - Jean Davy
显示剩余2条评论

4

代码:

return socket;

尝试复制套接字以返回并在函数退出时销毁原始套接字。不幸的是,套接字无法被复制(它们管理一个必须关闭的底层操作系统资源,因此系统必须确保该资源只存在一个引用,否则当第一个副本超出作用域时会出现严重问题)。
如其他答案中所建议的,您可以使用指针返回在堆上创建的对象(应使用shared_ptr进行管理,或者如果仅在单个位置使用它,则更有效地使用unique_ptr),或者如果您使用C++11,则可以使用移动构造函数来返回值:
return std::move (socket);

这样可以避免使用堆分配和指针,因此可能是更可取的解决方案。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接