Boost ASIO: нужно ли нам продолжать использовать async_read и писать внутри функции, вызываемой из async_read?

Я пытался понять логику в http://www.boost.org/doc/libs/1_53_0/doc/html/boost_asio/examples.html. Запрос в этом примере читается внутри connection.cpp, в методе start(), который вызывает:

socket_.async_read_some(boost::asio::buffer(buffer_),
      strand_.wrap(
        boost::bind(&connection::handle_read, shared_from_this(),
          boost::asio::placeholders::error,
          boost::asio::placeholders::bytes_transferred)));

Обратите внимание, что метод async_read_some задокументирован для возврата немедленно. Затем внутри обработчика чтения (connection::handle_read()) мы можем снова вызвать async_read_some, если синтаксический анализ возвращает boost::indeterminate. Какое преимущество это дает по сравнению с socket_.read_some(buffer), учитывая, что мы уже знаем, что работаем в отдельном потоке. Причина, по которой я спрашиваю, заключается в том, что я хочу немного изменить синтаксический анализ сообщения, чтобы вызывать read_some по запросу, но метод, который я имею в виду, не будет работать с асинхронным чтением.

Кроме того, связанный с этим вопрос: есть ли разница между

async_read_some()

и

boost::thread th([](){ ret = read_some(); handle_read(ret) });?


person Rollie    schedule 16.04.2013    source источник


Ответы (1)


HTTP-сервер Boost.Asio 3 Пример закодирован таким образом, что он не зависит от размера пула потоков. Таким образом, нет гарантии, что работа будет выполняться в отдельных потоках. Тем не менее, преимущество независимости состоит в том, что она лучше масштабируется при большем количестве подключений. Например, рассмотрим проблему C10K, которая исследует 10 000 одновременно подключенных клиентов. Синхронное решение может столкнуться с различными проблемами производительности или ограничениями ресурсов при работе с 10 000 клиентов. Кроме того, асинхронный характер помогает изолировать программу от изменений поведения в сети. Например, рассмотрим синхронную программу, которая имеет 3 клиента и 2 потока, но 2 из клиентов имеют большую задержку из-за увеличения шума в сети. Третий клиент может быть непреднамеренно затронут, если оба потока заблокированы в ожидании данных от других клиентов.

Если существует небольшое и конечное количество подключений, при этом каждое подключение обслуживается потоком, то разница в производительности между синхронным и асинхронным сервером может быть минимальной. По возможности часто рекомендуется избегать смешивания асинхронного и синхронного программирования, так как это может превратить сложное решение в сложное. Более того, большинство синхронных алгоритмов можно написать асинхронно.

Есть два основных различия между асинхронной операцией и синхронной операцией (даже выполняемой в выделенном потоке):

  • #P4# <блочная цитата> #P5# #P6#
  • Возможность отмены операции. Как отмечено в этом ответе, синхронные операции нельзя отменить с помощью cancel() функций-членов, предоставляемых Boost.Asio. Вместо этого приложению может потребоваться использовать механику более низкого уровня, например сигналы.
person Tanner Sansbury    schedule 16.04.2013
comment
Спасибо за описание - я не много программировал сокеты, так что это было поучительно. Моя единственная претензия к коду HTTP Server 3 заключается в том, что потребление слишком многословно; сервер 4 немного меньше, но все же кажется слишком большим. Я пытался написать if (++_reader != 'H' || ++_reader != 'T' || ++_reader != 'T' || ++_reader != 'P' || ++_reader != '/') return false;, а reader::operator++ вызвать read_some, если в его буфере закончились данные. К сожалению, не похоже, что это возможно с асинхронными операциями. - person Rollie; 16.04.2013