简体   繁体   English

套接字没有async_read

[英]Socket doesn't async_read

I'm new to async functions in boost::asio, and I've already had my first problem right here: 我是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;
    }
}

This piece of code is called at the main() function, and its purpose is to read some data from the socket that has just connected to it, and print "New connection" along with any error messages (See tcp_connection::handle_readConnection ). 这段代码在main()函数中调用,其目的是从刚刚与其连接的套接字读取一些数据,并打印“ New connection”以及任何错误消息(请参阅tcp_connection::handle_readConnection )。 Now, the problem is, although clients can connect to it and the boost::asio::async_read line in tcp_connection is called, handle_readConnection never is. 现在的问题是,尽管客户端可以连接到它,并且调用了tcp_connection中的boost::asio::async_read行, handle_readConnection从未如此。 Is there something I'm missing here? 我在这里想念什么吗? Thanks in advance. 提前致谢。

Do you actually connect to a remote socket? 您是否真的连接到远程套接字? Eg via socket::async_connect() ? 例如通过socket::async_connect() If not, where should it read the data from? 如果没有,应该从哪里读取数据?

One other problem is here: 另一个问题在这里:

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)));

You ask asio to read asynchronously into a buffer which is on the stack. 您要求asio异步读取堆栈中的缓冲区。 As soon as the function returns the address (which asio still stores) is invalid, and the read attempt could overwrite any kind of memory on the stack. 一旦函数返回地址(asio仍存储),该地址将无效,并且读取尝试可能会覆盖堆栈上的任何类型的内存。 Starting from there on you are more or less at undefined behavior, which might be the reason why the callback is never called. 从那里开始,您或多或少会遇到未定义的行为,这可能是从未调用回调的原因。 The buffer must always outlive the duration of the read attempt. 缓冲区必须始终超过读取尝试的持续时间。

Another thing where the lifetime must be valid is for io_ref .It must not be destroyed as long as any tcp_connection::pointer instance is active. 生存期必须有效的另一件事是io_ref ,只要任何tcp_connection::pointer实例处于活动状态,都不得销毁它。 Since we don't see this code, it's hard to tell. 由于我们看不到此代码,因此很难说出来。 If it's a global variable or part of the main function it's probably ok. 如果它是全局变量或主函数的一部分,则可能没问题。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM