GNU/Linux >> Tutoriales Linux >  >> Linux

¿Verificar conexión abierta o cerrada? (en C en Linux)

Uso send() en lugar de write() que no maneja ninguna señal:

bzero(buffer, MAX_SIZE_BUFFER);
n = read(sockfd, buffer, MAX_SIZE_BUFFER - 1);
printf("after read%d\n", n);
if (n <= 0)
{
    break;
}
n2 = send(newsockfd, buffer, n, MSG_NOSIGNAL);
if (n2 == -1)
{
    close(sockfd);
    close(newsockfd);
    return;
}
if (n2 != n)
{
    break;
}

La programación de sockets puede ser bastante complicada, porque a menudo no se sabe que se ha producido un error hasta mucho más tarde.

Por ejemplo, si la máquina en la que está escribiendo se apaga de manera anormal, la llamada de escritura puede tener éxito (porque pudo escribir en sus búferes internos del sistema operativo), solo para fallar durante la llamada de cierre.

A menos que tenga una forma de capa de aplicación para verificar que el socket esté activo (es decir, enviar un mensaje y solicitar una respuesta dentro de un período de tiempo), no tiene forma de saberlo. Si está utilizando un protocolo estándar, es posible que ya exista algo para manejar los errores.

Entonces, la respuesta corta es que debe verificar los retornos de error de casi todas las llamadas que tocan el socket (lectura, escritura, cierre, etc.).


Sorprendentemente, la forma de verificar si puede escribir en un socket es intentar escribir en él :-)

Si el socket se ha cerrado, obtendrá un -1 código de retorno de write y puedes examinar errno para ver cuál era el problema.

Si el socket aún es válido pero no puede escribir ningún dato en este momento, write devolverá 0. El read call también se comporta de manera similar, devolviendo -1 si hay un problema.

Básicamente, para write :

  • si obtienes un -1 , ha habido un problema y deberías marcar errno para ver si es recuperable o fatal.
  • Si obtienes un 0 , entonces no puede escribir nada en este momento (puede ser un retraso en la red o algún otro problema, pero definitivamente no (todavía) fatal).
  • Si obtiene un valor inferior al que deseaba, entonces algunos de los datos ha sido enviado. Ajuste sus punteros para que pueda intentar enviar el resto en el próximo ciclo. no asumir un valor de retorno positivo significa que se ha enviado todo el bloque.
  • Si obtiene el mismo número que el número de bytes que intentó enviar, el búfer completo ha sido aceptado para la entrega.
  • Si recibe más de lo que pidió que se le enviara, envíe un correo electrónico a los desarrolladores del kernel con un comentario mordaz. A Linus y otros les encantará eso :-)

Actualizar: Como ha señalado caf en los comentarios, se me olvidó tener en cuenta el manejo de la señal. Tienes que ignorar la señal de tubería rota o write fallará internamente al elevar esa señal.

Puede hacerlo insertando:

struct sigaction new_actn, old_actn;
new_actn.sa_handler = SIG_IGN;
sigemptyset (&new_actn.sa_mask);
new_actn.sa_flags = 0;
sigaction (SIGPIPE, &new_actn, &old_actn);

antes de comenzar a utilizar las funciones del socket. A continuación, puede utilizar:

sigaction (SIGPIPE, &old_actn, NULL);

para restaurar el manejo de la señal anterior.


Linux
  1. Verifique el límite de FD abierto para un proceso dado en Linux

  2. portapapeles de linux leer/escribir en C

  3. verifique todos los sockets abiertos en el sistema operativo Linux

  4. ¿Cómo agregar a un archivo en C, usando Abrir en modo O_APPEND en Linux?

  5. ¿Verificar si el puerto está abierto o cerrado en un servidor Linux?

¿Qué son los puertos? ¿Cómo verificar los puertos abiertos de Linux?

Cómo comprobar los puertos abiertos en Linux

Cómo comprobar que un puerto está abierto en un sistema Linux remoto

Cómo verificar todos los puertos abiertos en su sistema Linux

¿Cómo comprobar los puertos abiertos en Linux?

Todas las formas de verificar si un puerto está abierto en Linux