套接字没有async_read

时间:2019-01-19 23:07:39

标签: c++ boost-asio

我是boost :: asio中异步函数的新手,而我已经在这里遇到了第一个问题:

class tcp_connection
    : public boost::enable_shared_from_this<tcp_connection>
{
public:
    typedef boost::shared_ptr<tcp_connection> pointer;

    static pointer create(boost::asio::io_context& io_context)
    {
        return pointer(new tcp_connection(io_context));
    }

    tcp::socket& socket()
    {
        return socket_;
    }

    // Called when connection is made
    void start()
    {
        // New connection, read data
        boost::array<unsigned char, 128> buf;
        boost::asio::async_read(socket_, boost::asio::buffer(buf),
            boost::bind(&tcp_connection::handle_readConnection, shared_from_this(), boost::asio::placeholders::error, boost::ref(buf)));
    }

private:
    tcp_connection(boost::asio::io_context& io_context)
        : socket_(io_context)
    {
    }

    void handle_write(const boost::system::error_code& error,
        size_t bytes_transferred)
    {
    }

    void handle_readConnection(const boost::system::error_code& error, boost::array<unsigned char, 128> buf)
    {
        std::cerr << error.message() << std::endl;
        std::cout << "New connection!" << std::endl;
    }

    tcp::socket socket_;
    std::string message_;
};

class tcp_server
{
public:
    tcp_server(boost::asio::io_context& io_context)
        : acceptor_(io_context, tcp::endpoint(tcp::v4(), 13))
    {
        start_accept();
    }

private:
    // Creates a socket and initializes an async accept operation to wait for a new connection
    void start_accept()
    {
        tcp_connection::pointer new_connection =
            tcp_connection::create(acceptor_.get_executor().context());

        acceptor_.async_accept(new_connection->socket(),
            boost::bind(&tcp_server::handle_accept, this, new_connection,
                boost::asio::placeholders::error));
    }

    // Called by start_accept. Creates a new connection and runs start_accept again to search for new clients
    void handle_accept(tcp_connection::pointer new_connection,
        const boost::system::error_code& error)
    {
        if (!error)
        {
            new_connection->start();
        }

        start_accept();
    }

    tcp::acceptor acceptor_;
};

int main()
{
    try {
        boost::asio::io_context io_context;
        tcp_server server(io_context);

        io_context.run();
    }
    catch (std::exception& e)
    {
        std::cerr << e.what() << std::endl;
    }
}

这段代码在main()函数中调用,其目的是从刚刚与其连接的套接字读取一些数据,并打印“ New connection”以及任何错误消息(请参见{{1 }})。现在的问题是,尽管客户端可以连接到它,并且tcp_connection中的tcp_connection::handle_readConnection行被调用,但boost::asio::async_read却从未如此。我在这里想念什么吗?预先感谢。

1 个答案:

答案 0 :(得分:0)

您实际上连接到远程套接字吗?例如。通过socket::async_connect()吗? 如果没有,应该从哪里读取数据?

另一个问题在这里:

boost::array<unsigned char, 128> buf;
        boost::asio::async_read(socket_, boost::asio::buffer(buf),
            boost::bind(&tcp_connection::handle_readConnection, shared_from_this(), boost::asio::placeholders::error, boost::ref(buf)));

您要求asio异步读取堆栈中的缓冲区。 一旦函数返回地址(asio仍存储),该地址将无效,并且读取尝试可能会覆盖堆栈上的任何类型的内存。 从那里开始,您或多或少会遇到未定义的行为,这可能是从未调用回调的原因。 缓冲区必须始终超过读取尝试的持续时间。

生存期必须有效的另一件事是io_ref。只要任何tcp_connection::pointer实例处于活动状态,都不得销毁它。由于我们看不到此代码,因此很难说出来。如果它是全局变量或主函数的一部分,则可能没问题。