2010-05-20 7 views
80

¿Cómo puedo tratar de leer datos del socket con tiempo de espera? Sé, seleccione, pselect, poll, tiene un campo de tiempo de espera, pero el uso de ellos desactiva "tcp fast-path" en tcp reno stack.Linux: ¿hay una lectura o recv desde el socket con timeout?

La única idea que tengo es el uso de recv (fd, ..., MSG_DONTWAIT) en un bucle

+0

También existe la opción de utilizar hilos :) pero las señales de rosca todavía necesitaba – osgx

Respuesta

147

Usted puede utilizar la función setsockopt para establecer un tiempo de espera en las operaciones de recepción:

SO_RCVTIMEO

establece el valor de tiempo de espera que especifica la cantidad máxima de tiempo una función de entrada espera hasta que completa. Es acepta una estructura timeval con el número de segundos y microsegundos que especifica el límite de cuánto tiempo esperar para completar una operación de entrada a . Si una operación de recepción tiene bloqueado durante este tiempo sin recibiendo datos adicionales, deberá devolver con un conteo parcial o errno establecido en [EAGAIN] o [EWOULDBLOCK] si no se reciben datos . El valor predeterminado para esta opción es cero, lo que indica que una operación de recepción no deberá exceder el tiempo de espera. Esta opción toma una estructura timeval. Tenga en cuenta que no todas las implementaciones permiten configurar esta opción.

// LINUX 
struct timeval tv; 
tv.tv_sec = timeout_in_seconds; 
tv.tv_usec = 0; 
setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, (const char*)&tv, sizeof tv); 

// WINDOWS 
DWORD timeout = timeout_in_seconds * 1000; 
setsockopt(socket, SOL_SOCKET, SO_RCVTIMEO, (const char*)&timeout, sizeof timeout); 

// MAC OS X (identical to Linux) 
struct timeval tv; 
tv.tv_sec = timeout_in_seconds; 
tv.tv_usec = 0; 
setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, (const char*)&tv, sizeof tv); 

Reportedly en Windows esto debe hacerse antes de llamar bind. He comprobado experimentalmente que se puede hacer antes o después de bind en Linux y OS X.

+2

¿Funcionará para linux 2.6 tcp? udp? – osgx

+5

Sí lo hará. Muchas gracias – osgx

+0

Esto no funciona en Windows .... – Mendes

0

Instalar un controlador para SIGALRM, a continuación, utilizar alarm() o ualarm() ante un bloqueo regular de recv(). Si la alarma suena, el recv() devolverá un error con errno establecido en EINTR.

+8

alarmas (y señales) son el camino equivocado para este tarea. Si quiero usar tcp fast path, entonces necesito una latencia mínima. Las señales son lentas – osgx

+1

@osgx La señal solo se produce si hay un tiempo de espera. –

13

Aquí es un simple código para agregar el tiempo de espera a la función recv mediante sondeo en C:

struct pollfd fd; 
int ret; 

fd.fd = mySocket; // your socket handler 
fd.events = POLLIN; 
ret = poll(&fd, 1, 1000); // 1 second for timeout 
switch (ret) { 
    case -1: 
     // Error 
     break; 
    case 0: 
     // Timeout 
     break; 
    default: 
     recv(mySocket,buf,sizeof(buf), 0); // get your data 
     break; 
} 
-1

LINUX

struct timeval tv; 
tv.tv_sec = 30;  // 30 Secs Timeout 
tv.tv_usec = 0;  // Not init'ing this can cause strange errors 
setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, (const char*)&tv,sizeof(struct timeval)); 

VENTANAS

DWORD timeout = SOCKET_READ_TIMEOUT_SEC * 1000; 
setsockopt(socket, SOL_SOCKET, SO_RCVTIMEO, (const char*)&timeout, sizeof(timeout)); 

NOTA: usted ha puesto esta configuración antes de bind() llamada a la función para la ejecución adecuada

+2

Esta pregunta ya ha sido respondida hace años. ¿Qué nuevo valor trae tu solución? –

+0

Has puesto esta configuración antes de la llamada a la función bind() para ejecutarla correctamente Esta parte no se menciona en ans – vivek

Cuestiones relacionadas