2012-09-13 41 views
14

Tengo una aplicación que necesita enviar datos a un servidor en algún momento. La manera más fácil sería cerrar la conexión y luego abrirla nuevamente cuando quiero enviar algo. Pero quiero mantener la conexión abierta así que cuando quiero enviar datos, primero compruebe la conexión utilizando esta función:Compruebe si el socket está conectado o no

bool is_connected(int sock) 
{ 
    unsigned char buf; 
    int err = recv(sock,&buf,1,MSG_PEEK); 
    return err == -1 ? false : true; 
} 

La parte mala es que esto no funciona. Se cuelga cuando no hay datos para recibir. ¿Que puedo hacer? ¿Cómo puedo verificar si la conexión aún está abierta?

+3

http://stackoverflow.com/questions/4142012/how-to-find-the-socket-connection-state-in-c – BoBTFish

Respuesta

17

No marque primero y luego envíe. Es un esfuerzo desperdiciado y no funcionará de todos modos: el estado puede cambiar entre cuando lo haces y cuando lo envías. Simplemente haz lo que quieras hacer y maneja el error si falla.

Para comprobar el estado, utilice:

int error_code; 
int error_code_size = sizeof(error_code); 
getsockopt(socket_fd, SOL_SOCKET, SO_ERROR, &error_code, &error_code_size); 
+1

Verdadero ... pero a veces es útil verificar si un socket todavía está conectado. Establecerlo en no-bloque, y luego leer con peek_msg es una buena forma de obtener un código de error para verificar que el socket todavía esté conectado. –

+2

@RafaelBaptista ¿Por qué? * Usar * lo comprobará. Las pruebas primero no pueden funcionar de manera confiable, por la razón que da David arriba. – EJP

+0

@EJP: Quiero verificar que la conexión del cliente esté activa, así que no desperdicio recursos en caso de que no lo esté. – che

12

Debe habilitar el comportamiento de no bloqueo configurando O_NONBLOCK usando fcntl. Una manera fácil, pero no estándar de hacer una lectura sin bloqueo sería utilizar:

recv(sock, &buf, 1, MSG_PEEK | MSG_DONTWAIT); 

Después, necesidad cheque errno si falla. Puede fallar con EAGAIN o puede fallar con EBADF o ENOTCONN etc.


Obviamente, la manera más simple y más limpio que lidiar con esto sería evitar "olvidar" si el socket está conectado o no. Observará si el socket se desconecta una vez que recv devuelve 0 o send devuelve EPIPE.

+2

esto no será detectar todas las fallas de conexión. Solo un envío() puede hacer eso. – EJP

+0

@EJP Eso es cierto, de hecho. Solo estaba mejorando la solución de la operación. Lo que sugiere es la única solución a prueba de balas, pero implica el envío. – cnicutar

2

El uso predeterminado de TCP no permite la detección muy oportuna de conectores muertos (fuera del cierre normal) así que sugiero que una función "is_connected" como esta es en gran parte inútil para todos los propósitos prácticos. Considere la posibilidad de implementar un keep-alive de capa de aplicación y realizar un seguimiento si está activo en función de las respuestas oportunas (o la falta de ellas).

editar: después de publicar, veo el enlace de BoBTFish, que efectivamente es lo mismo.

Cuestiones relacionadas