Cómo configurar el tiempo de espera de conexión del socket
1. Primero configure el indicador en modo sin bloqueo y prepárese para llamar a la función de conexión en modo sin bloqueo.
2. En circunstancias normales, llame a connect. El protocolo de enlace de tres vías requiere algo de tiempo; una llamada sin bloqueo devolverá un error siempre que no se pueda completar de inmediato, por lo que aquí se devolverá EINPROGRESS, lo que indica que la conexión se está estableciendo pero aún no se ha completado.
3. Establezca el socket actual en el conjunto de descriptores de socket de lectura (fd_set rset) y escriba el conjunto de descriptores de socket (fd_set
wset) (use la macro FD_ZERO(), FD_SET()) y establezca el tiempo de espera (struct
timeval *timeout)
4. Llamar a select( socket, &rset, &wset, NULL, timeout )
Devolver 0 indica que se ha agotado el tiempo de espera de conexión
Si el tiempo de espera que configuró es superior a 75 segundos, no es necesario hacer esto, porque el límite de tiempo de espera para la conexión en el kernel es de 75 segundos.
Creo que todos tienen muy clara la importancia del socket en la programación de redes. Socket también es un socket. En la programación de sockets, cuando se menciona el concepto de tiempo de espera, podemos pensar en tres a la vez: tiempo de espera de envío. , tiempo de espera de recepción y tiempo de espera de selección (Nota:
La función de selección no solo se usa para sockets, sino que también se usa a menudo en la programación de sockets. Cuando se conecta al host de destino, este tiempo de espera no está configurado). por nosotros. Sin embargo, en circunstancias normales, este tiempo de espera es muy largo y la conexión es un método de bloqueo. Si un host no se puede conectar, aún puede tolerar la espera de que vuelva la conexión. Si su programa intenta conectarse a varios hosts, puede encontrar varios. los que no se pueden conectar. Al usar el host, estará tan cargado que no podrás soportarlo. Déjame dejar de hablar y hablar sobre mi método primero. Si crees que lo dominas, no necesitas leer más. Si aún no lo entiendes, estoy dispuesto a compartirlo contigo. Este artículo utiliza un programa que ya está en Linux como ejemplo, pero el método es el mismo cuando se usa en Windows. Solo es cuestión de cambiar algunos nombres de funciones.
Hay dos formas de establecer un tiempo de espera para conectarse en Linux. Uno son algunos parámetros del sistema. No hablaré de este método porque no puedo explicarlo claramente: P. Tampoco se implementa mediante programación. Otro método es implementar el tiempo de espera de conexión disfrazado. De lo que quiero hablar es de este método. El principio es el siguiente:
1. Crear socket
2. Configure el socket en modo sin bloqueo
3. Llame a connect()
4. Utilice select() para comprobar si se puede escribir en el descriptor del socket (tenga en cuenta que se puede escribir)
5. Determine el resultado de connect() en función del resultado devuelto por select()
6. Configure el socket en modo de bloqueo (si su programa no necesita usar el modo de bloqueo, este paso se omite, pero generalmente se usa el modo de bloqueo, que es más fácil de administrar)
Si está interesado en Si Si está familiarizado con la programación de redes, sabrá cómo escribir su programa tan pronto como le explique el proceso. Aquí hay un programa que escribí solo como referencia.
/******************************
* Tiempo de espera para conectar ()
* Escrito por Kerl W
***************************** ***** */
#include
#include
#define TIME_OUT_TIME 20 //tiempo de espera de conexión 20 segundos
int main(int argc, char **argv)
{
………………
int sockfd = socket(AF_INET, SOCK_STREAM, 0);
if(sockfd < 0) exit(1);
struct sockaddr_in serv_addr;
………/ /Rellena la estructura serv_addr con la dirección del servidor
int error=-1, len;
len = sizeof(int);
timeval tm;
fd_set set;
unsigned long ul = 1;
ioctl(sockfd, FIONBIO, &ul); /p>
bool ret = false;
if( connect(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) ==
-1) p>
{
tm.tv_set = TIME_OUT_TIME;
tm.tv_uset = 0;
FD_ZERO(&set);
FD_SET(sockfd, &set) ;
if( select(sockfd+1, NULL, &set, NULL, &tm) > 0)
{
getsockopt (sockfd, SOL_SOCKET, SO_ERROR, &error, (socklen_t *)&len);
if(error == 0) ret = true;
si no ret = false;
} else ret = false;
}
else ret = true;
ul = 0;
ioctl(sockfd , FIONBIO, &ul); / /Establecer en modo de bloqueo
if(!ret)
{
close( sockfd );
fprintf(stderr , "¡No se puede conectar el servidor!n");
return;
}
fprintf( stderr , "Conectado!n");
//También puede realizar las operaciones de envío y recepción de paquetes a continuación
…………
}
Los fragmentos de código anteriores son solo como referencia y también se proporcionan para principiantes. Algunos consejos, puede encontrar información relevante sobre las funciones principales utilizadas, seleccione,
ioctl,
getsockopt, el uso específico está aquí
No entraré en detalles aquí. Sólo necesita escribir ligeramente man
Además, algunos puntos que necesito explicar son que aunque usamos ioctl para configurar el socket en modo sin bloqueo, select en sí mismo es bloqueado y el tiempo de bloqueo es su tiempo de espera determinado llamando a select.
está determinada por la variable de estructura timeval apuntada por el puntero de variable de tipo timeval. La estructura timeval consta de un miembro que representa el número de segundos y un miembro que representa el número de microsegundos (generalmente,). Configuramos Solo la cantidad de segundos es suficiente, establecemos la cantidad de microsegundos en 0 (nota: 1 segundo equivale a 1 millón de microsegundos). Otro parámetro de la función de selección que vale la pena mencionar es el puntero variable del tipo fd_set que usamos anteriormente. Antes de la llamada, esta variable almacena el descriptor que se verificará con select. Después de la llamada, para el programa anterior, hay descriptores grabables. Podemos usar la macro FD_ISSET para verificar si un determinado descriptor está en él. Como solo tengo un descriptor de socket aquí, no utilicé la macro FD_ISSET para verificar si sockfd está en el conjunto después de llamar a select. De hecho, es necesario agregar este juicio. Sin embargo, utilicé getockopt para verificar, de modo que pueda determinar si el socket está realmente conectado, porque solo usamos select disfrazado para verificar si está conectado. De hecho, select verifica si se puede escribir. que se puede escribir cuando se cumple cualquiera de las tres condiciones siguientes:
1) El número de bytes de control disponibles en el búfer de envío del socket es mayor o igual que el búfer de envío del socket. El valor actual del valor bajo. límite de marea, y i) el socket está conectado, o ii) el socket no requiere una conexión (modo UDP)
2) la mitad de escritura de la conexión está cerrada.
3) Hay un error de socket pendiente.
De esta manera, necesitamos usar la función getockopt para obtener información actual del socket para determinar si está realmente conectado. Cuando no está conectado, también puede indicar qué errores se produjeron. , mi programa No tiene tantos estados marcados, simplemente significa conectable/no conectable.
Permítanme hablar sobre los resultados de probar este programa. Hice pruebas para 3 situaciones:
1. Si la red de la máquina de destino es normal
puede conectarse al host de destino y puede enviar y recibir paquetes con éxito en modo de bloqueo.
2. Cuando la máquina de destino se desconecta de la red
Después de esperar el tiempo de espera establecido (20 segundos en el programa anterior), se muestra que el host de destino no se puede conectar.
3. Desconecte la red de la máquina de destino antes de ejecutar el programa y restaure la red de la máquina de destino dentro del período de tiempo de espera.
Antes de restaurar la conexión de red del host de destino, el programa espera. Después de restaurar el host de destino, el programa muestra que. La conexión con el host de destino es exitosa y puede realizar con éxito operaciones de envío y recepción de paquetes en modo de bloqueo.
Los resultados de las pruebas de las diversas situaciones anteriores muestran que este método de configurar el tiempo de espera de conexión es completamente factible. Encapsulé este tipo de conexión con tiempo de espera en mi propia biblioteca de clases y la usé en un sistema de monitoreo. Hasta ahora, se está ejecutando normalmente. La ventaja de este tiempo de espera de conexión programática en comparación con el método de modificar los parámetros del sistema es que solo se usa en su programa y no afecta el sistema.