2010-12-29 9 views
20

Al leer otras entradas de desbordamiento de pila y la documentación boost::asio, he confirmado que no hay llamadas de lectura/escritura ASIO síncronas que también proporcionan un tiempo de espera fácil de usar como parámetro para la llamada.C++ Boost ASIO: ¿cómo leer/escribir con un tiempo de espera?

Estoy en medio de la conversión de una aplicación de socket de Linux de la vieja escuela con llamadas selectivas (2) que emplean tiempos de espera, y tengo que hacer más o menos lo mismo.

¿Cuál es la mejor manera de hacer esto en boost::asio? Si observamos la documentación de Asio, hay muchos ejemplos confusos de varias cosas que hacer con temporizadores, pero estoy bastante confundido.

Me encantaría ver un ejemplo fácil de leer de esto: Leer desde un socket, pero esperar un máximo de X segundos después de lo cual la función o regresa sin nada, o regresa con lo que fue capaz para leer desde el socket antes de que expire el tiempo de espera.

+3

¿Puede explicar qué es confuso sobre este ejemplo: http://think-async.com/Asio/asio-1.4.7/src/examples/timeouts/blocking_tcp_client.cpp: la lógica esencial es enviar 2 tareas asíncronas, una lectura/escritura y la otra un tiempo de espera si la lectura/escritura regresa primero mata el temporizador de fecha límite, si el temporizador de la fecha de entrega regresa la lógica es la lectura/escritura sigue siendo excepcional, a partir de ahí se continúa con su lógica de tiempo de espera. muy muy simple. –

+2

Hay un caso de esquina que podría surgir en la red hf que está relacionado con la puesta en cola de las devoluciones de llamada. el tiempo de espera cb está en cola, luego la lectura/escritura está en cola. te encuentras con el timeout cb y comienzas a ejecutar la lógica de tiempo de espera cuando en realidad la lectura/escritura se completó, una posible solución que he visto es algo similar al bloqueo de doble comprobación, en resumen, realizar un tiempo de espera secundario cuando regrese el primer tiempo de espera pero entonces esto tiene el mismo problema, ¿qué pasa si la lectura/escritura está en cola después de que el segundo tiempo de espera es la cola? –

+2

Solo recuerda que un tiempo de espera es una condición difícil, estás diciendo que si no obtengo algo en cierta cantidad de tiempo, haré algo específico, esto incluye el hecho de que la lectura/escritura puede haber ocurrido y está en camino hacia ti, eso no cambia el hecho de que no la has recibido hasta el momento. –

Respuesta

6

Esto ha aparecido en las listas de correo asio, hay un ticket solicitando la función también. Para resumir, se sugiere utilizar métodos asíncronos si desea tiempos de espera y cancelaciones.


Si no se puede convertir a los métodos asíncronos, es posible que trate los SO_RCVTIMEO y SO_SNDTIMEO opciones de conector. Se pueden configurar con setsockopt, el descriptor se puede obtener con el método boost::asio::ip::tcp::socket::native. La página man 7 socket hombre dice

SO_RCVTIMEO y SO_SNDTIMEO Especificar la recepción o el envío de los tiempos de espera hasta que informar un error . El argumento es una struct timeval. Si una función de entrada o salida bloquea durante este período de tiempo , y los datos han sido enviados o recibidos, el valor de retorno de esa función será la cantidad de datos transferidos; si no se ha transferido ningún dato y se ha alcanzado el tiempo de espera , -1 es devuelto con errno configurado en EAGAIN o EWOULDBLOCK igual que si el zócalo se hubiera especificado en sea no bloqueante. Si el tiempo de espera es establecido en cero (valor predeterminado), la operación nunca expirará. Los tiempos de espera solo tienen efecto para las llamadas al sistema que realizan E/S de socket (por ejemplo, read (2), recvmsg (2), send (2), sendmsg (2)); tiempos de espera no tienen ningún efecto para select (2), sondeo (2), epoll_wait (2), etc.

+1

¿Leyó la respuesta de CH a la solicitud? ASIO replica la funcionalidad del sistema operativo en C++, si necesita algún tipo de funcionalidad de tiempo de espera, puede realizarlo utilizando los componentes de bits que proporciona ASIO. –

5

utilicé algunos asio docs para producir este:

class TimeoutAdjust 
{ 
public: 
    TimeoutAdjust(unsigned int dwTimeout) : m_dwTimeout(dwTimeout) {}; 

    template<class Protocol> 
    int level(const Protocol& p) const {return SOL_SOCKET;} 

    template<class Protocol> 
    int name(const Protocol& p) const {return SO_SNDTIMEO;} 

    template<class Protocol> 
    const void* data(const Protocol& p) const {return &m_dwTimeout;} 

    template<class Protocol> 
    size_t size(const Protocol& p) const {return sizeof(m_dwTimeout);} 
private: 
    unsigned int m_dwTimeout; 
}; 

Uso:

TimeoutAdjust adjust(5000); 
sSocket.set_option(adjust); 

Lo depuré y parece hacer lo que se supone que debe hacer.

+1

Lo que he leído aquí es que 'SO_SNDTIMEO' toma' timeval', en lugar de 'unsigned int'. http://linux.die.net/man/7/socket – updogliu

+0

Ah, MS usa un DWORD para SO_SNDTIMEO. Parece que timeval es un par de entradas largas, así que ten cuidado con el lector. MS docs: http://msdn.microsoft.com/en-ca/library/windows/desktop/ms740532(v=vs.85).aspx – ArtHare

+2

Después de usar el código anterior, recibo una excepción Excepción: set_option: Inválido argumento. Si tiene algún código de referencia, por favor comparta el mismo. – asim

Cuestiones relacionadas