chriskohlhoff / asio

Asio C++ Library
http://think-async.com/Asio
4.81k stars 1.2k forks source link

Working the function async_read_some() #1306

Closed hanusek closed 1 year ago

hanusek commented 1 year ago

Hello! I have a problem with the function async_read_some(). I am running cyclicly the function receiveAsyncWithTimeout() by a timer.

Expected working The function receiveAsyncWithTimeout() should read all messages from my server.

Problems

  1. bytesTransferred and bytesReadable are different.
  2. Messages are received weirdly. First one frame, after about 10 seconds the rest.

Boost version: 1.77

output:

readHandle bytesReadable: 0 bytesTransferred: 1112

pseudocode:

class Timer : public GenericTimer
{
public:
    explicit Timer(boost::asio::io_context &context)
        : _context(context)
        , _timer(_context)
    {
    }

    void stop()
    {
        _timer.cancel();
    }

    void setInterval(const std::chrono::steady_clock::duration &interval) noexcept override
    {
        _timer.expires_from_now(interval);
        asyncWait();
    }

private:
    void asyncWait() noexcept
    {
        _timer.async_wait(
            [this](const boost::system::error_code &ec)
            {
                if(ec)
                {
                    _errorCallback(fmt::format("Timer error: {}", ec.message()));
                    return;
                }

                if(_callback)
                {
                    _callback();
                }
            });
    }

private:
    boost::asio::io_context &_context;
    boost::asio::steady_timer _timer;
};

class TlsSocket 
{
public:
    TlsSocket(boost::asio::io_context &io_context,
              const std::string &endpoint);
private:
    boost::asio::io_context &_iocontext;
    boost::asio::ssl::context _ctx;
    boost::asio::ssl::stream<boost::asio::ip::tcp::socket> _socket;
    std::vector<uint8_t> _recvBuffer;
    std::vector<uint8_t> _sendBuffer;
    size_t _bytesReadable{0};
}

void TlsSocket::readHandle(const boost::system::error_code &ec, std::size_t bytesTransferred)
{
    if(_bytesReadable == 0 && bytesTransferred > 0)
    {
        std::cout << "readHandle ERROR bytesReadable: " << _bytesReadable
                  << " bytesTransferred: " << bytesTransferred << std::endl;
        return;
    }

/// .. any code
}

void TlsSocket::receiveAsyncWithTimeout()
{
    boost::asio::socket_base::bytes_readable command(true);
    _socket.lowest_layer().io_control(command);
    _bytesReadable = command.get();

     _socket.async_read_some(boost::asio::buffer(_recvBuffer),
                            boost::bind(&TlsSocket::readHandle,
                                        this,
                                        boost::asio::placeholders::error,
                                        boost::asio::placeholders::bytes_transferred));
}
hanusek commented 1 year ago

I've solved it. My conclusion: I should not use boost::asio::socket_base::bytes_readable with async_read_some.