Es posible tener un socket UDP recibiendo simultáneamente desde un punto extremo remoto y enviando a un punto final remoto diferente. Sin embargo, según la documentación de Boost.Asio Threads and Boost.Asio, generalmente no es seguro realizar llamadas simultáneas en un solo objeto.
Por lo tanto, esto es seguro:
thread_1 | thread_2
--------------------------------------+---------------------------------------
socket.async_receive_from(...); |
socket.async_send_to(...); |
y esto es seguro:
thread_1 | thread_2
--------------------------------------+---------------------------------------
socket.async_receive_from(...); |
| socket.async_send_to(...);
pero esto se especifica como no estar segura:
thread_1 | thread_2
--------------------------------------+---------------------------------------
socket.async_receive_from(...); | socket.async_send_to(...);
|
Tenga en cuenta que algunas funciones , como boost::asio::async_read
, son operación compuesta, y tiene restricciones de seguridad de hilos adicionales.
Si cualquiera de lo siguiente es cierto, entonces no hay sincronización adicional tiene que ocurrir, ya que el flujo será implícitamente síncrono:
- Todas las llamadas de socket se producen dentro de los manipuladores, y
io_service::run()
solamente se invoca desde un solo hilo.
async_receive_from
y async_send_to
solo se invocan dentro de la misma cadena de operaciones asincrónicas. Por ejemplo, el ReadHandler
pasado a async_receive_from
invoca async_send_to
, y el WriteHandler
pasado a async_send_to
invoca async_receive_from
.
void read()
{
socket.async_receive_from(..., handle_read); --.
} |
.-----------------------------------------------'
| .----------------------------------------.
V V |
void handle_read(...) |
{ |
socket.async_send_to(..., handle_write); --. |
} | |
.-------------------------------------------' |
| |
V |
void handle_write(...) |
{ |
socket.async_receive_from(..., handle_read); --'
}
Por otro lado, si hay varios hilos que hacen potencialmente llamadas simultáneas a la toma de corriente, entonces la sincronización tiene que ocurrir.Considere realizar la sincronización al invocar las funciones y los controladores a través de boost::asio::io_service::strand, o mediante el uso de otros mecanismos de sincronización, como Boost.Thread's mutex.
Además de la seguridad de la rosca, debe tenerse en cuenta la gestión de la vida útil de los objetos. Si el servidor necesita procesar solicitudes múltiples al mismo tiempo, tenga cuidado con la propiedad de buffer
y endpoint
para cada cadena request-> process-> response. Según la documentación de async_receive_from
, la persona que llama conserva la propiedad del buffer y endpoint. Como tal, puede ser más fácil administrar la vida útil de los objetos a través del boost::shared_ptr. De lo contrario, si la cadena es lo suficientemente rápida como para no requerir cadenas concurrentes, simplifica la administración, permitiendo que se utilice el mismo buffer y endpoint por solicitud.
Finalmente, la clase socket_base::reuse_address
permite una toma en obligarse a una dirección que ya está en uso. Sin embargo, no creo que es una solución aplicable en este caso, ya que se utiliza generalmente:
- Para TCP para permitir un proceso para reiniciar y escuchar al mismo puerto, incluso si el puerto está en un estado
TIME_WAIT
.
- Para que UDP permita que varios procesos se vinculen al mismo puerto, permitiendo que cada proceso reciba y difunda a través de multidifusión.
Por favor, especifique su pregunta real. ¿Está funcionando su configuración y está buscando confirmación de que está bien por diseño? ¿O no está funcionando, y si no es qué error observas? ¿O está preguntando cómo enlazar otro socket al puerto del servidor? – mtrw
@mtrw ¿Es posible enlazar otro socket al mismo puerto de servidor? De esa manera usaría diferentes enchufes para enviar repeticiones. Lo que ocurre es que creo que mi configuración puede causar un mal funcionamiento del servidor. – Ghita
Por favor, edite su pregunta para aclarar en lugar de agregar comentarios –