Проблема с async_read, когда длина пакета больше или меньше - PullRequest
0 голосов
/ 11 апреля 2020

Я проверил пример форсирования и много тестировал, но я думаю, что async_read не запускается должным образом, когда пакет (полученные данные) меньше или больше ожидаемого буфера.

Там пример сервер и клиент SSL на boost.org. В примере клиента после того, как рукопожатие выполнено, вызывается send_request(), а затем send_request() с точной длиной отправленного текста. Что произойдет, если send_request() не знает о длине пакета? Для этого есть три ситуации (под длиной буфера я подразумеваю length аргумент в boost::asio::buffer(reply_, length)):

Длина пакета равна длине буфера Нет проблем, мы получили пакет.

Длина пакета> длина буфера Мы получаем столько же, сколько длина пакета, то, что осталось, получено в другой ход, проблема в том, что мы не можем получить остальную часть пакета, помещая еще один send_request() в лямбда-тело, остатки получат, когда будет вызван другой send_request() (и т. д.):

void receive_response(std::size_t length)
{
    boost::asio::async_read(
        socket_,
        boost::asio::buffer(reply_, length),
        [this](const boost::system::error_code& error, std::size_t length)
        {
            if (!error)
            {
                std::cout << "Reply: ";
                std::cout.write(reply_, length);
                std::cout << "\n";
                receive_response(length);           <---------- this one
            }
            ...
        }
    );
}

Длина пакета <длина буфера </strong> Я немного изменил лямбда-квитирование, чтобы можно было смоделировать этот, как в следующем фрагменте кода, я также изменил методы receive_response() и send_request(), чтобы они не вызывали друг друга. Я ожидал, что лямбда async_readreceive_response()) будет вызвана после двух async_writesend_request()) заполнения буфера, но этого не произошло.

void handshake()
{
    socket_.async_handshake(
        boost::asio::ssl::stream_base::client,
        [this](const boost::system::error_code& error)
        {
            if (!error)
            {
                receive_response(10);       //Trigger async_read for length 10
                send_request();             //Send a string of length 5
                send_request();             //Send a string of length 5
            }
            ...
        }
    );
}

Можно предположить используя async_read_some(). Я тоже это проверял. К счастью, он вызывается первым send_request(), но второй send_request() не вызывает async_read_some() лямбду (я поместил еще один receive_response() в тело лямбды, чтобы сделать al oop).

void receive_response(std::size_t length)
{
    socket_.async_read_some(
        boost::asio::buffer(reply_, length),
        [this](const boost::system::error_code& error, std::size_t length)
        {
            ...
            receive_response(length);
            ...
        }
    );
}
...