Сокет не async_read - PullRequest
       13

Сокет не async_read

0 голосов
/ 20 января 2019

Я новичок в асинхронных функциях в 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 (),и его цель - прочитать некоторые данные из только что подключенного сокета и распечатать «Новое соединение» вместе с любыми сообщениями об ошибках (см. tcp_connection::handle_readConnection).Теперь проблема в том, что, хотя клиенты могут подключаться к нему и вызывается строка boost::asio::async_read в tcp_connection, handle_readConnection никогда не вызывается.Есть что-то, чего я здесь не хватает?Заранее спасибо.

1 Ответ

0 голосов
/ 20 января 2019

Вы действительно подключаетесь к удаленному разъему? Например. через 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. Поскольку мы не видим этот код, трудно сказать. Если это глобальная переменная или часть основной функции, то, вероятно, все в порядке.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...