Cómo configurar el tiempo de espera de conexión
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. , reciba el tiempo de espera y seleccione el tiempo de espera (Nota:
select
La función no solo se usa para sockets, sino que se usa más en la programación de sockets Después de conectarse al destino Cuando). Al usar el host, este tiempo de espera no lo establecemos 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, se puede tolerar que se restablezca la conexión si su programa intenta conectarse. Me temo que hay varios hosts cuando te encuentras con varios hosts que no se pueden conectar
será abrumador. 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
toma como ejemplo un programa que ya está en Linux, pero el método es el mismo cuando se usa en Windows. Es solo 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); //Establecer en modo sin bloqueo
bool ret = false; p>
if( connect (sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) ==
-1)
{
tm.tv_set = TIME_OUT_TIME; p>
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;
else ret = false;
} else ret = false;
}
else ret = true;
ul = 0;
ioctl(sockfd, FIONBIO, &ul); p>
if( !ret)
{
close( sockfd );
fprintf(stderr , "¡No se puede conectar el servidor! n") ;
return;
}
fprintf( stderr , "Connected!n");
//También puedes realizar paquetes operaciones de envío y recepción a continuación
………………
}
Los fragmentos de código anteriores son solo como referencia y también brindan algunos consejos para principiantes. Las funciones principales utilizadas son seleccionar,
ioctl,
getsockopt. Puede encontrar información relevante. No entraré en detalles sobre el uso específico aquí. Solo necesita escribir suavemente ma en Linux.
n
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.
El último parámetro de timeval está determinado por la variable de estructura timeval apuntada por el puntero variable de tipo timeval. La estructura timeval consta de una que representa el número de segundos y otra que representa. el número de microsegundos (tipo largo
), generalmente simplemente configuramos el número de segundos y establecemos el número de microsegundos en 0 (Nota: 1 segundo es igual 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 un descriptor grabable. Podemos usar la macro
FD_ISSET para verificar una determinada descripción. el símbolo está entre ellos. 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 lo está. escribible, y para escribible, significa que se puede escribir cuando se cumple cualquiera de las siguientes tres condiciones:
1) Búfer de envío de socket El número de bytes de control disponibles es mayor o igual que el valor actual del límite bajo del búfer de envío del socket, y i) el socket está conectado, o ii) el socket no requiere 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 en diversas situaciones
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.
Al conectar un socket sin bloqueo, generalmente se usa en las siguientes situaciones:
1. El protocolo de enlace de tres vías lleva tiempo, lo que depende de las condiciones específicas de la red. Por supuesto que es posible fracasar. Durante el protocolo de enlace de tres vías, no necesitamos esperar a que se complete el protocolo de enlace de tres vías. Podemos usar este tiempo para completar otras cosas y luego, cuando se completen, verificar si la conexión está establecida (también Eso). es si se completa el protocolo de enlace de tres vías).
2. Puedes utilizar esta tecnología para establecer múltiples conexiones al mismo tiempo. (Muy utilizado en navegadores WEB).
3.El tiempo de espera de la conexión tarda mucho en ser notificado. Si pensamos que expirará después de más de 0,1 segundos (independientemente de si realmente se agota), podemos usar I/ sin bloqueo. O combinación
Selecciona para completar.
Cuando se utiliza E/S sin bloqueo para utilizar la conexión, es más complicado determinar si se ha establecido una conexión. Debe seguir los siguientes pasos para completar
1. si usa Para operaciones de conexión sin bloqueo, la conexión aún puede regresar correctamente, lo que significa que la conexión sin bloqueo
también puede regresar después de que se completa la conexión de tres vías. Esta situación generalmente ocurre cuando el servidor y. host están en la misma máquina, por lo que el primer paso es juzgar si connect regresa correctamente. Si regresa correctamente, realice el procesamiento de devolución correctamente
; de lo contrario, vaya al paso 2
<. p>2. Configure fd_set (si no lo ha visto, lea primero la introducción de la función de selección), deje que la función de selección supervise las propiedades de lectura y escritura del socket al mismo tiempo. legible y escribible, ingrese el paso 3. Si se puede escribir pero no legible, vaya al paso 4.3. Si llegamos a este paso, debemos llamar a getsockopt para realizar una evaluación adicional. Esto implica un problema de trasplante. Si ocurre un error en getsockopt, la implementación de Berkeley devolverá 0 y, si es Solaris, devolverá -1. Se recomienda manejar ambos (si no comprende, consulte primero la función getsockopt y la opción socket
). Según el valor de error devuelto por getsockopt a través del parámetro, si el valor es 0, significa que el establecimiento del enlace se completó. Si no es 0, significa que el establecimiento del enlace no se completó.
4. Si puedes llegar hasta aquí, significa que la conexión está establecida.
Finalmente, incluso si concluye que el vínculo no está establecido, solo significa que es posible que el proceso de protocolo de enlace de tres vías no se complete.