2009-05-31 14 views
8

Ok antes que nada me gustaría mencionar lo que estoy haciendo es completamente ético y sí, estoy escaneando puertos.Tiempo de espera del socket en C++ Linux

El programa funciona bien cuando el puerto está abierto pero cuando llego a un socket cerrado el programa se detiene por un tiempo muy largo porque no hay una cláusula de tiempo de espera. A continuación se muestra el siguiente código

int main(){ 

    int err, net; 
    struct hostent *host; 
    struct sockaddr_in sa; 

    sa.sin_family = AF_INET; 

    sa.sin_port = htons(xxxx); 
    sa.sin_addr.s_addr = inet_addr("xxx.xxx.xxx.xxx"); 

    net = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); 
    err = connect(net, (struct sockaddr *)&sa, sizeof(sa)); 

    if(err >= 0){ cout << "Port is Open"; } 
    else { cout << "Port is Closed"; } 

} 

He encontrado esto en desbordamiento de pila, sino que simplemente no tiene sentido para mí con un comando de select().

Pregunta: ¿Podemos hacer que el tiempo de espera de la función connect() no espere un año para que vuelva con un error?

+14

No hay necesidad de explicar por qué lo necesita - es como pedir direcciones a banco y cada vez que explica que desea retirar dinero y no a robar .. – stefanB

+1

: D bien puesto. pero no estoy retirando dinero: D –

Respuesta

7

Lo más fácil es configurar una alarm y han connect ser interrumpido con una señal (ver UNP 14.2):


signal(SIGALRM, connect_alarm); /* connect_alarm is you signal handler */ 
alarm(secs); /* secs is your timeout in seconds */ 
if (connect(fs, addr, addrlen) < 0) 
{ 
    if (errno == EINTR) /* timeout */ 
     ... 
} 
alarm(0); /* cancel alarm */ 

Aunque el uso de select no es mucho más difícil :)
Es posible que desee aprender sobre raw sockets también.

+1

Gracias, eso funcionó tuve que mirar la alarma y la señal para entender cómo funciona, pero no obstante, hace lo que pedí en la lata. Gracias: D –

+0

'sigaction' debería ser generalmente preferido a 'signal', que tiene diferentes comportamientos en diferentes UNIXes. – ephemient

+0

Es cierto, el código fue citado directamente de Stevens. –

2

Si está inactivo al usar IO de bloqueo para hacer esto, debe investigar la llamada a setsockopt(), específicamente el indicador SO_SNDTIMEO (u otros indicadores, dependiendo de su sistema operativo).

Tenga en cuenta que estas banderas no son confiables/portátiles y pueden implementarse de manera diferente en diferentes plataformas o diferentes versiones de una plataforma determinada.

La forma tradicional/mejor de hacerlo es mediante el enfoque nonblocking que utiliza select(). En caso de que sea nuevo en los sockets, uno de los mejores libros es TCP/IP Illustrated, Volume 1: The Protocols. Es en Amazon a: http://www.amazon.com/TCP-Illustrated-Protocols-Addison-Wesley-Professional/dp/0201633469

+0

SO_SNDTIMEO no funcionará en connect() – ernesto

1

RudeSocket resuelto el problema

me encontré con un archivo lib que se prueba en Linux Fedora (No estoy seguro acerca de Windows) que me da la opción de tiempo de espera. A continuación puede encontrar un ejemplo muy simple.

#include <rude/socket.h> 
#include <iostream> 

using namespace std; 
using namespace rude; 

Socket soc; 
soc.setTimeout(30, 5); 

//Try connecting 
if (soc.connect("xxx.xxx.xxx.xxx", 80)){ 

    cout << "Connected to xxx.xxx.xxx.xxx on Port " << 80 << "\n"; 
} 

//connections Failed 
else{ 
    cout << "Timeout to xxx.xxx.xxx.xxx on Port " << 80 << "\n"; 
} 

soc.close(); 

Aquí hay un enlace a la DevSite

Cuestiones relacionadas