2016-09-22 3 views
0

В настоящее время я работаю с клиентом async rest, используя boost :: asio :: io_service. Я пытаюсь сделать клиента своего рода услугой для более крупной программы. Идея заключается в том, что клиент будет выполнять асинхронные HTTP-запросы в API останова независимо от потока, выполняющего основную программу. Таким образом, внутри в клиенте будет другой поток, ожидающий отправки запроса. Чтобы передать запросы клиента я использую io_service и io_service :: работа инициализированную io_service. Я почти повторил пример, приведенный в этом уроке - logger_service.hpp. Моя проблема заключается в том, что когда в примере они отправляют работу службе, вызываемый обработчик является простой функцией. В моем случае, когда я делаю асинхронные вызовы, как это (я необходимое сделать, чтобы запустить все instancies следующих объектов и еще некоторые таким образом, чтобы иметь возможность установить подключение к сети):boost async rest client

boost::asio::io_service io_service_; 
boost::asio::io_service::work work_(io_service_); //to prevent the io_service::run() to return when there is no more work to do 
boost::asio::ssl::stream<boost::asio::ip::tcp::socket> socket_(io_service_); 

в основной программе я делаю следующие вызовы:

client.Connect(); 
... 
client.Send(); 
client.Send(); 
... 

псевдокод Some клиента:

void MyClass::Send() 
{ 
... 
io_service_.post(boost::bind(&MyClass::AsyncSend, this); 
... 
} 


void MyClass::AsyncSend() 
{ 
... 
boost::io_service::asio::async_write(socket, streamOutBuffer, boost::bind(&MyClass::handle_send, this)); 
... 
} 

void MyClass::handle_send() 
{ 
boost::io_service::asio::async_read(socket, streamInBuffer, boost::bind(&MyClass::handle_read, this)); 
} 

void MyClass::handle_read() 
{ 
// ....treatment for the received data... 
    if(allDataIsReceived)  
     FireAnEvent(ReceivedData); 
    else 
    boost::io_service::asio::async_read(socket, streamInBuffer, boost::bind(&MyClass::handle_read, this)); 
} 

Как описано в документации 'post 'метод запрашивает io_service для вызова данного обработчика и немедленно возвращается. Мой вопрос в том, будут ли вложенные обработчики, например :: handle_send в AsyncSend, вызванный сразу после (когда ответ HTTP готов), когда используется post()? Или обработчики будут вызваны в другом порядке, отличном от того, который определяется порядком вызовов post()? Я задаю этот вопрос, потому что, когда я звоню только раз клиент-> Отправить(), клиент, кажется, «отлично работает». Но когда я делаю 2 последовательных вызова, как в приведенном выше примере, клиент не может завершить первый вызов, а затем выполняет второй, а после некоторых хаотических исполнений в конце 2 операции завершаются с ошибкой.

Есть ли способ сделать то, что я описываю, выполнить целую цепочку асинхронов до выполнения другого.

Я надеюсь, что я достаточно ясно с моим описанием :)

+0

Вы можете сделать это синхронно или добавить переменную условия, чтобы проверить, закончился ли предыдущий вызов. (Предполагая, что вы правильно обрабатываете SSL-соединение) – Blacktempel

ответ

0

привет Blacktempel,

Благодарит Вас за предоставленные комментарии и идеи, но тем не менее я работаю над проектом, который требует использования асинхронных вызовов. На самом деле, поскольку я новичок с Boost my question и пример, который я дал, были неправильными в части функции handle_read. Я добавлю несколько строк в примере, чтобы более четко понять, в какой ситуации я (был). На самом деле во многих примерах может быть все они, которые рассматривают тему, как создать асинхронный клиент, очень простые ... Все они просто показывают, как связать различные обработчики и обработку данных, когда «handle_read» называется всегда «печатать некоторые данные на экране» внутри этого же обработчика чтения. Который, я думаю, совершенно ошибочен по сравнению с реальными проблемами! Никто не будет просто распечатывать данные и заканчивать выполнение ее программы ...! Обычно после получения данных происходит другое обращение, которое должно начаться, например FireAnEvent().Под влиянием плохих примеров я сделал это «FireAnEvent» внутри обработчика чтения, что, очевидно, совершенно неверно! Это плохо сделать, потому что, делая такие вещи, «handle_read» никогда не сможет выйти или выйти слишком поздно. Если этот обработчик не завершится, цикл io_service также не завершится. И если ваше дальнейшее обращение требует еще раз для вашего асинхронного клиента сделать что-то, это запустит/перезапустит (я не уверен в деталях) цикл io_service. В моем случае я делал несколько вызовов для асинхронного клиента таким образом. В конце я увидел, как io_service всегда начинался, но никогда не заканчивался. Даже после того, как все лечение закончилось, я никогда не видел, чтобы io_service остановился. Итак, наконец, я позволю клиенту async заполнить некоторую глобальную переменную полученными данными внутри handle_read и не называть напрямую другую функцию, такую ​​как FireAnEvent. И я переместил вызов этой функции (FireAnEvent) сразу после io_service.run(). И это сработало, потому что после завершения метода run() я знаю, что цикл полностью закончен! Надеюсь, мой ответ поможет людям :)