Повысить сокет ASIO читать N байтов не более не менее и ждать, пока они придут или исключение таймаута? - PullRequest
6 голосов
/ 13 июля 2011

Создание простого TCP-сервера на основе примеров , но все равно не получается, как создать сокет, который будет считывать некоторое количество байтов и, если их будет недостаточно, будет ждать. Мне нужно, чтобы это НЕ было асинхронной операцией.

#include <iostream>
#include <boost/asio.hpp>

#ifdef _WIN32
#include "Windows.h"
#endif

using namespace boost::asio::ip;
using namespace std;

int main(){
    int m_nPort = 12345;
    boost::asio::io_service io_service;
    tcp::acceptor acceptor(io_service, tcp::endpoint(tcp::v4(), m_nPort));

    cout << "Waiting for connection..." << endl;

    tcp::socket socket(io_service);
    acceptor.accept(socket);
    cout << "connection accepted" << endl;
    try
    {
        socket.send(boost::asio::buffer("Start sending me data\r\n"));
    }
    catch(exception &e)
    {
        cerr << e.what() << endl; //"The parameter is incorrect" exception
    }
}

Как получить 10000 байт и делать это либо до тех пор, пока все 10000 не придут, ИЛИ до 1000 миллисекунд, и не сгенерировать исключение?

Ответы [ 2 ]

6 голосов
/ 13 июля 2011

Boost 1.47.0 только что ввел функцию тайм-аута для basic_socket_iostream, а именно методов expires_at и expires_from_now.

Вот пример, основанный на вашем фрагменте:

#include <iostream>
#include <boost/asio.hpp>

using namespace boost::asio::ip;
using namespace std;

int main(){
    int m_nPort = 12345;
    boost::asio::io_service io_service;
    tcp::acceptor acceptor(io_service, tcp::endpoint(tcp::v4(), m_nPort));

    cout << "Waiting for connection..." << endl;

    tcp::iostream stream;
    acceptor.accept(*stream.rdbuf());
    cout << "Connection accepted" << endl;
    try
    {
        stream << "Start sending me data\r\n";

        // Set timeout in 5 seconds from now
        stream.expires_from_now(boost::posix_time::seconds(5));

        // Try to read 12 bytes before timeout
        char buffer[12];
        stream.read(buffer, 12);

        // Print buffer if fully received
        if (stream) // false if read timed out or other error
        {
            cout.write(buffer, 12);
            cout << endl;
        }
    }
    catch(exception &e)
    {
        cerr << e.what() << endl;
    }
}

Эта программа работает для меня в Linux.

Обратите внимание, что я не рекомендую использовать тайм-ауты вместо асинхронной операции с таймером дедлайна.Тебе решать.Я просто хотел показать, что таймауты возможны с basic_socket_iostream.

0 голосов
/ 13 июля 2011

Как сделать тайм-аут и сгенерировать исключение?

Вообще говоря, при использовании асинхронных методов вы получаете только таймауты и возможность отмены. Существует несколько способов решения этой проблемы, которые обсуждались в SO в предыдущих вопросах . Я настоятельно рекомендую вам изучить асинхронные методы, это значительно облегчит понимание логики.

Тем не менее, вы можете представить синхронный интерфейс, используя асинхронные методы внизу. Это делается в примере блокировки тайм-аута TCP-клиента , предоставляемом библиотекой Asio. Остерегайтесь, однако, пример не совсем прямой (хотя и хорошо прокомментированный) из-за его инверсии управления и использования лямбда-функций. Я предлагаю вам изучить использование асинхронных методов непосредственно перед попыткой чего-то подобного.

Как получить 10000 байт?

используйте бесплатную функцию async_read , раздел замечаний описывает именно то, что вам нужно

Примечания

Эта перегрузка эквивалентна вызову:

boost::asio::async_read(
    s, buffers,
    boost::asio::transfer_all(),
    handler);

где ваш буфер имеет размер 10 000 байт.

...