Impulse el streambuf de ASIO

Estoy confundido sobre la secuencia de entrada y la secuencia de salida en las clases boost asio :: streambuf.

De acuerdo con los ejemplos de código (para enviar datos) en la documentación, parece que el búfer que representa la secuencia de entrada se utiliza para escribir en el zócalo y el que representa la secuencia de salida se usa para la lectura.

Ejemplo –

boost::asio::streambuf b; std::ostream os(&b); os << "Hello, World!\n"; // try sending some data in input sequence size_t n = sock.send(b.data()); b.consume(n); // sent data is removed from input sequence 

Ahora, ¿hay un problema de nomenclatura?

La nomenclatura para boost::asio::streambuf es similar a la que se define en el estándar C ++, y se usa en varias clases en la biblioteca de plantillas estándar, donde los datos se escriben en una secuencia de salida y los datos se leen de una secuencia de entrada . Por ejemplo, uno podría usar std::cout.put() para escribir en la secuencia de salida, y std::cin.get() para leer desde la secuencia de entrada.

Al controlar manualmente las streambuf entrada y salida de streambuf , el ciclo de vida general de los datos es el siguiente:

  • Los búferes se asignan con prepare() para la secuencia de salida.
  • Después de que los datos hayan sido escritos en los buffers de la secuencia de salida, los datos serán commit() ed. Estos datos confirmados se eliminan de la secuencia de salida y se anexan a la secuencia de entrada desde la cual se pueden leer.
  • Los datos se leen de los búferes de la secuencia de entrada obtenidos a través de data() .
  • Una vez que los datos han sido leídos, pueden ser eliminados de la secuencia de entrada por el consume() de consume() .

Cuando se utilizan operaciones Boost.Asio que operan en streambuf o transmiten objetos que utilizan un streambuf , como std::ostream , las secuencias de entrada y salida subyacentes se administrarán correctamente. Si, en cambio, se proporciona un búfer a una operación, como pasar passing prepare() a una operación de lectura o data() a una operación de escritura, entonces uno debe manejar explícitamente el commit() y el consume() .

Aquí hay una versión anotada del código de ejemplo que escribe directamente desde un streambuf a un socket:

 // The input and output sequence are empty. boost::asio::streambuf b; std::ostream os(&b); // prepare() and write to the output sequence, then commit the written // data to the input sequence. The output sequence is empty and // input sequence contains "Hello, World!\n". os < < "Hello, World!\n"; // Read from the input sequence, writing to the socket. The input and // output sequences remain unchanged. size_t n = sock.send(b.data()); // Remove 'n' bytes from the input sequence. If the send operation sent // the entire buffer, then the input sequence would be empty. b.consume(n); 

Y aquí está el ejemplo anotado para leer desde un socket directamente en un streambuf . Las anotaciones suponen que la palabra "hola" se ha recibido, pero aún no se ha leído, en el socket:

 boost::asio::streambuf b; // prepare() 512 bytes for the output sequence. The input sequence // is empty. auto bufs = b.prepare(512); // Read from the socket, writing into the output sequence. The // input sequence is empty and the output sequence contains "hello". size_t n = sock.receive(bufs); // Remove 'n' (5) bytes from output sequence appending them to the // input sequence. The input sequence contains "hello" and the // output sequence has 507 bytes. b.commit(n); // The input and output sequence remain unchanged. std::istream is(&b); std::string s; // Read from the input sequence and consume the read data. The string // 's' contains "hello". The input sequence is empty, the output // sequence remains unchanged. is >> s; 

Observe cómo en los ejemplos anteriores, los objetos de vapor manejados cometieron y consumieron las secuencias de salida y entrada del streambuf. Sin embargo, cuando se usaron los búferes (es decir, data() y prepare() ), el código necesario para manejar explícitamente commits y consume.

“Todo es relativo”

Albert Einstein

La documentación dice:

Los caracteres escritos en la secuencia de salida de un objeto basic_streambuf se anexan a la secuencia de entrada del mismo objeto.

Desde el punto de vista del streambuf leerá de su secuencia de salida y escribirá en su secuencia de entrada lo que podría parecer un poco invertido, pero puede pensar en el streambuf como una tubería para que las cosas tengan sentido.

Desde el punto de vista del usuario (cualquier cosa que use el streambuf , incluidos los sockets) ahora, escribirá en la secuencia de streambuf del streambuf y leerá de su secuencia de entrada lo que parece más natural.

Entonces, sí, de la misma manera, la izquierda y la derecha se invierten según lo que se enfrenta, las entradas y las salidas se invierten dependiendo de qué lado lo mires.

“No creas cada cita que lees en Internet, porque no dije eso”

Albert Einstein