Pregunta

Estoy escribiendo servidor utilizando boost.asio. He leído y escribir memoria intermedia para cada conexión y el uso asynchronized función de lectura / escritura (async_write_some / async_read_some).

Con búfer de lectura y async_read_some, no hay problema. Sólo la invocación de la función async_read_some está bien porque búfer de lectura es de sólo lectura en controlador de lectura (significa en mismo hilo por lo general).

Sin embargo, escribir amortiguar tenga que acceder desde varios hilos por lo que necesita ser bloqueado para modificar.

PRIMERA PREGUNTA!

¿Hay alguna manera de evitar la dependencia de buffer de escritura?

escribo mi propio paquete en búfer de pila y copiarlo en el buffer de escritura. A continuación, llamar a la función async_write_some para enviar el paquete. De esta manera, si envío de dos paquetes en serie, ¿es correcto que invoca la función async_write_some dos veces?

SEGUNDA PREGUNTA!

¿Qué es la forma común para la escritura asynchronized en la programación del zócalo?

Gracias por la lectura.

¿Fue útil?

Solución

Respuesta # 1:

Tiene razón en que bloqueo es un enfoque viable, pero hay una manera mucho más simple de hacer todo esto. Boost tiene una pequeña construcción en ASIO llama strand. Cualquier devolución de llamada que se ha envuelto el uso de la hebra se puede serializar, garantizado, no importa que el hilo ejecuta la devolución de llamada. Básicamente, se ocupa de cualquier bloqueo para ti.

Esto significa que usted puede tener tantos escritores como desee, y si todos ellos están envueltos por el mismo hebra (así, compartir su sola hebra entre todos sus escritores) que se ejecutarán en serie . Una cosa a tener en cuenta es asegurarse de que no está intentando utilizar el mismo tampón real en la memoria para hacer todas las escrituras. Por ejemplo, esto es lo que debe evitar:

char buffer_to_write[256];  // shared among threads

/* ... in thread 1 ... */
memcpy(buffer_to_write, packet_1, std::min(sizeof(packet_1), sizeof(buffer_to_write)));
my_socket.async_write_some(boost::asio::buffer(buffer_to_write, sizeof(buffer_to_write)), &my_callback);

/* ... in thread 2 ... */
memcpy(buffer_to_write, packet_2, std::min(sizeof(packet_2), sizeof(buffer_to_write)));
my_socket.async_write_some(boost::asio::buffer(buffer_to_write, sizeof(buffer_to_write)), &my_callback);

No, estás compartiendo el buffer de escritura real (buffer_to_write). Si usted hizo algo como esto en su lugar, va a estar bien:

/* A utility class that you can use */
class PacketWriter
{
private:
  typedef std::vector<char>  buffer_type;

  static void WriteIsComplete(boost::shared_ptr<buffer_type> op_buffer, const boost::system::error_code& error, std::size_t bytes_transferred)
  {
    // Handle your write completion here
  }

public:
  template<class IO>
  static bool WritePacket(const std::vector<char>& packet_data, IO& asio_object)
  {
    boost::shared_ptr<buffer_type> op_buffer(new buffer_type(packet_data));

    if (!op_buffer)
    {
      return (false);
    }

    asio_object.async_write_some(boost::asio::buffer(*op_buffer), boost::bind(&PacketWriter::WriteIsComplete, op_buffer, boost::asio::placeholder::error, boost::asio::placeholder::bytes_transferred));
  }
};

/* ... in thread 1 ... */
PacketWriter::WritePacket(packet_1, my_socket);

/* ... in thread 2 ... */
PacketWriter::WritePacket(packet_2, my_socket);

En este caso, sería de ayuda si usted pasó su hebra en WritePacket también. Se entiende la idea, sin embargo.

Respuesta # 2:

Creo que ya está tomando un enfoque muy bueno. Una sugerencia que iba a ofrecer es utilizar async_write en lugar de async_write_some para que se le garantiza todo el búfer está escrito antes de su devolución de llamada se llama.

Otros consejos

Lo sentimos, pero tiene dos opciones:

  1. serializar el estado de escritura, ya sea con las cerraduras, o mejor iniciar un hilo escritor independiente que lee las peticiones de una cola, otros hilos entonces puede apilar hasta peticiones en el cola sin demasiada contención (se requeriría alguna mutexing).

  2. Dar a cada hilo de su propia escritura toma! Esta es realmente la mejor solución si el programa en el otro extremo del alambre puede apoyarlo.

Se podría Cola sus modificaciones y realizarlas en los datos en el controlador de escritura.

Red lo más probable ser la parte más lenta del tubo (asumiendo que su modificación no están computacionalmente caro), por lo que se podía realizar modificaciones mientras que la capa de conexión es el envío de la los datos anteriores.

En caso que usted está manejando gran número de clientes con frecuencia de conexión / desconexión echar un vistazo a IO puertos de finalización o mecanismo similar.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top