Как узнать, есть ли данные, доступные для чтения из сокета в boost :: asio? - PullRequest
3 голосов
/ 16 декабря 2009

Я использую библиотеку Boost ASIO для написания клиентской программы TCP.

Протокол начинается со строки баннера при подключении, после которой следует '\ r \ n' Я могу отправлять команды в любое время так же, как SMTP.

Однако сервер также может отправлять мне данные, когда я их не запрашиваю, и они завершаются с помощью \ r \ n * 1005

У меня есть строка, подобная этой, чтобы прочитать и проанализировать начальный баннер подключения Что означает, прекратить чтение, когда я получу "\ r \ n".

boost::asio::streambuf response_;
...
boost::asio::async_read_until(socket_, response_, "\r\n",
            boost::bind(&PumpServerClient::HandleReadBanner, this,
                boost::asio::placeholders::error));

Но в разное время я хочу задать вопрос, есть ли данные? если есть, читайте до "\ r \ n". Я чувствую, что мне нужна функция просмотра, но я не вижу, где это.

Хорошо, возможно, я смогу снова вызвать async_read_until. Но учти это ... это никогда не заканчивается. Отладка продолжающегося чтения появляется один раз. Очевидно, он ждет вечно, чтобы завершить, но никогда не делает.

void client::HandleReadRequest(const boost::system::error_code& err)
{
    if (!err){
        // Got some data, print it out
        std::ostringstream ss;
        ss << &response_;

        std::cout << ss.str() << std::endl;

         // Keep reading...
        boost::asio::async_read_until(socket_, response_, "\r\n",
          boost::bind(&client::HandleReadRequest, this, boost::asio::placeholders::error));

        std::cout << "keep reading" << std::endl;
    }
    else
    {
        std::cout << "Error: " << err.message() << "\n";
    }
}

Хорошо, я думаю, я понял это сейчас. Я не смотрел на достаточно полный пример, чтобы основывать свой код.

Это похоже на вызов:

повышение :: ASIO :: async_read_until (socket_, response_, "\ r \ n", повышение :: Bind (и клиент :: HandleReadRequest, этот, повышение :: ASIO :: заполнители :: ошибок)); означает, что когда в буфере response_ появляется \ r \ n, вызывается функция HandleReadRequest. Мне нужно только вызвать async_read_until один раз. если не вызван запрос на запись, тогда мне нужно снова выполнить чтение ... кажется ... ну, теперь он работает по крайней мере.

Ответы [ 2 ]

3 голосов
/ 16 декабря 2009

Взглянув на документацию , я пойду с socket_base::bytes_readable, как в:

boost::asio::ip::tcp::socket socket(io_service); 
...
boost::asio::socket_base::bytes_readable command(true);
socket.io_control(command);
std::size_t bytes_readable = command.get();
2 голосов
/ 16 декабря 2009

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

Если вы «загляните» в сокет, я подозреваю, что он не будет работать так, как вы ожидаете, потому что данные будут прочитаны asio и переданы в обработчик чтения, как только они станут доступны, они будут только «готовы читать "в течение крошечного интервала, пока вызывается обработчик. Хотя это может работать, пока на сокете не запущен async_read.

В случае с async_read_until вы, вероятно, просто захотите опубликовать еще один запрос на чтение, когда вызывается ваш обработчик чтения.

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