boost::asio::buffer: Obtener el tamaño de búfer y la prevención de desbordamiento de búfer?

Tengo los dos siguientes funciones para el envío y recepción de paquetes.

void send(std::string protocol)
{
char *request=new char[protocol.size()+1];
request[protocol.size()] = 0;
memcpy(request,protocol.c_str(),protocol.size());
request_length = std::strlen(request);
boost::asio::write(s, boost::asio::buffer(request, request_length));
}
void receive()
{
char reply[max_length];
size_t reply_length = boost::asio::read(s, boost::asio::buffer(reply, request_length));
std::cout << "Reply is: ";
std::cout.write(reply, reply_length);
std::cout << "\n";
}

Las preguntas se refieren a esta parte boost::asio::buffer(reply, request_length) donde la longitud de la solicitud es la longitud de una cadena, la cual fue inicialmente el programa de instalación cuando se envió el paquete. ¿Cómo puedo comprobar el tamaño del búfer sin saber request_length? Otra pregunta es ¿cómo puedo prevenir el desbordamiento de búfer?

OriginalEl autor pandoragami | 2013-02-25

3 respuestas

  1. 15

    Para obtener el tamaño de la memoria intermedia, el boost::asio::buffer_size() función puede ser utilizada. Sin embargo, en tu ejemplo, es más probable que sea de poca utilidad para usted.

    Como se explica en el búfer descripción, Boost.Asio uso del búfer de clases para representar los búferes. Estas clases proporcionan una abstracción y proteger Impulso.Asio operaciones contra desbordamiento del búfer. Aunque el resultado de boost::asio::buffer() se pasa a las operaciones, los meta-datos, tales como el tamaño del búfer o su tipo subyacente, no se transmite. También, estos amortiguadores no son dueños de la memoria, de modo que es el de las aplicaciones de la responsabilidad de velar por la memoria subyacente sigue siendo válido para toda la duración de la búfer de abstracción de la vida.

    La boost::asio::buffer() función proporciona una forma conveniente de crear el buffer de clases, donde el tamaño de la memoria intermedia se deduce a partir del tipo que sea posible. Cuando El Impulso.Asio es capaz de deducir la longitud de búfer, entonces Boost.Asio operaciones no invocar un desbordamiento de búfer cuando se utiliza el resultado tipo de búfer. Sin embargo, si el código de la aplicación especifica el tamaño del buffer a boost::asio::buffer(), entonces es el de las aplicaciones de la responsabilidad de asegurarse de que el tamaño no es mayor que el que subyace a la memoria.

    Cuando la lectura de los datos, un buffer es necesario. La pregunta fundamental es: ¿cómo hace uno para saber cuánta memoria para asignar, si Boost.Asio no transmite el tamaño. Hay un par de soluciones a este problema:

    • Consulta el zócalo de la cantidad de datos que está disponible a través de socket::disponible(), a continuación, asignar el búfer en consecuencia.

      std::vector<char> data(socket_.available());
      boost::asio::read(socket_, boost::asio::buffer(data));
    • Utilizar una clase que Aumentar.Asio puede crecer en la memoria, como boost::asio::streambuf. Algunas operaciones, tales como boost::asio::leer() aceptar streambuf objetos como su buffer y asignar la memoria que se requiere para la operación. Sin embargo, una finalización enfermedad debe ser; de lo contrario, la operación continuará hasta que el buffer está lleno.

      boost::asio::streambuf data;
      boost::asio::read(socket_, data,
      boost::asio::transfer_at_least(socket_.available()));
    • Como Öö Tiib sugiere, incorporar longitud como parte del protocolo de comunicación. Compruebe el Impulso.Asio ejemplos para ejemplos de protocolos de comunicación. Centrarse en el protocolo, no necesariamente en el Impulso.Asio API.

      • En un tamaño fijo de protocolo, tanto los datos productor y el consumidor utilice el mismo tamaño de mensaje. Como el lector sabe que el tamaño del mensaje, el lector puede asignar un búfer de antemano.
      • En una longitud variable de protocolo, los mensajes son a menudo se divide en dos partes: un encabezado y un cuerpo. El encabezado es normalmente de tamaño fijo, y puede contener varios meta-información, tales como la longitud del cuerpo. Esto permite que un lector para leer un encabezado en un buffer de tamaño fijo, el extracto de la longitud del cuerpo, asignar un búfer para el cuerpo, luego de leer el cuerpo.

        //Read fixed header.
        std::vector<char> data(fixed_header_size);
        boost::asio::read(socket_, boost::asio::buffer(data));
        protocol::header header(data);
        network_to_local(header); //Handle endianess.
        //Read body.
        data.resize(header.body_length());
        boost::asio::read(socket_, boost::asio::buffer(data));  
        protocol::body body(data);
        network_to_local(body); //Handle endianess.    
    Grandes cosas. boost::asio::streambuff con boost::asio::read_until() funcionado bien para mí en el caso de que los mensajes de final con un delimitador.

    OriginalEl autor Tanner Sansbury

  2. 5

    Normalmente un protocolo de comunicaciones que utiliza ya sea fija la longitud de los mensajes que contienen un encabezado que indica la longitud del mensaje.

    Boost.Asio documentación en línea contiene un gran conjunto de ejemplos y tutoriales para que tal vez debería empezar a partir de ahí. Wikipedia es una buena fuente para explicar la transmisión de datos terminología, impulso asio documentación no hacerlo.

    Ya he mirado a través del impulso asio tutoriales pero para los que sólo brillo sobre los ejemplos y no explican en gran detalle lo que la función de llamadas, lo que volver, etc. Sé que yo podría mirar en el hpp de archivos también pero eso es como una aguja en el pajar y aún más inútil de los ejemplos. Además, yo estoy seguro de que hay un montón de cosas que no se dijo en el impulso de los ejemplos/tutoriales pero sólo se encuentra en el hpp de archivos que puede llevar años de práctica para consumir.
    quizás el impulso asio ejemplos esperar que la gente se familiarice con el concepto de la comunicación digital y el significado de términos relacionados como protocolos, clientes, servidores, solicitudes, etc. utilizados en los ejemplos. Sugiero contra la ingeniería inversa esos conocimientos de código, son más fáciles de fuentes para aprender todo eso.
    El ejemplos no explican lo que el API debido a que se documenta en el referencia de la sección. El Boost.Asio de la biblioteca es complejo, no es complicado. Hay una gran cantidad de información en la documentación, y puede ser vale la pena tomar el tiempo para familiarizarse con las diferentes partes de la documentación.
    gracias que el enlace de referencia es útil. Nunca sabía que existía.

    OriginalEl autor Öö Tiib

  3. 1

    Creo que tu pregunta es confusa, pero esto podría ayudar a:

    void receive() {
    enum { max_length = 1024 };
    char reply[max_length];
    size_t reply_length;
    std::cout << "Reply is: ";
    while ( (reply_length = ba::read(s, basio::buffer(reply, max_length))) > 0) {
    std::cout.write(reply, reply_length);
    }
    std::cout << "\n";
    }
    El boost::asio::buffer(,) devuelve lo que exactamente. Veo que devuelve algo en el ba::read(s,buffer(,)) pero, ¿qué es?
    Un tipo que representa la memoria, pero no es el propietario de la memoria. El función ayuda a adaptar los tipos utilizados de modo que cumplan los requisitos de tipo de muchos de los Boost.Asio operaciones. Este visión general proporciona un poco de información.
    Usted no tiene que pasar max_length a asio::buffer() en este ejemplo. (Desde asio puede conseguir utilizando sizeof.)

    OriginalEl autor perreal

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *