que - socket udp
¿Cómo encontrar el estado de conexión socket en C? (9)
Debes intentar usar: función getpeername .
ahora, cuando la conexión está inactiva, obtendrá errno: ENOTCONN - El zócalo no está conectado. lo que significa para ti ABAJO.
más (si no hay otros fallos), el código de retorno será 0 -> lo que significa ARRIBA.
recursos: página de manual: http://man7.org/linux/man-pages/man2/getpeername.2.html
Tengo una conexión TCP. El servidor simplemente lee los datos del cliente. Ahora, si se pierde la conexión, el cliente recibirá un error al escribir los datos en la tubería (tubería rota), pero el servidor todavía escucha en esa tubería. ¿Hay alguna manera de que pueda encontrar si la conexión es UP o NO?
Hay una manera fácil de verificar el estado de la conexión de socket a través de una llamada de poll
. Primero, debe sondear el socket, ya sea que tenga POLLIN
evento POLLIN
.
- Si el socket no está cerrado y hay datos para leer, la
read
devolverá más de cero. - Si no hay nuevos datos en el socket, entonces
POLLIN
se establecerá en 0 enrevents
- Si el socket está cerrado, la bandera
POLLIN
se establecerá en una y la lectura devolverá 0.
Aquí hay un pequeño fragmento de código:
int client_socket_1, client_socket_2;
if ((client_socket_1 = accept(listen_socket, NULL, NULL)) < 0)
{
perror("Unable to accept s1");
abort();
}
if ((client_socket_2 = accept(listen_socket, NULL, NULL)) < 0)
{
perror("Unable to accept s2");
abort();
}
pollfd pfd[]={{client_socket_1,POLLIN,0},{client_socket_2,POLLIN,0}};
char sock_buf[1024];
while (true)
{
poll(pfd,2,5);
if (pfd[0].revents & POLLIN)
{
int sock_readden = read(client_socket_1, sock_buf, sizeof(sock_buf));
if (sock_readden == 0)
break;
if (sock_readden > 0)
write(client_socket_2, sock_buf, sock_readden);
}
if (pfd[1].revents & POLLIN)
{
int sock_readden = read(client_socket_2, sock_buf, sizeof(sock_buf));
if (sock_readden == 0)
break;
if (sock_readden > 0)
write(client_socket_1, sock_buf, sock_readden);
}
}
La única forma de detectar de manera confiable si un socket aún está conectado es intentar enviar datos periódicamente. Por lo general, es más conveniente definir un paquete de ''ping'' de nivel de aplicación que los clientes ignoren, pero si el protocolo ya está especificado sin tal capacidad, debería poder configurar los SO_KEEPALIVE TCP para hacer esto configurando la opción SO_KEEPALIVE socket. He vinculado a la documentación de winsock, pero la misma funcionalidad debería estar disponible en todas las pilas de zócalos similares a BSD.
La opción TCP keepalive socket (SO_KEEPALIVE) ayudaría en este escenario y cerraría el socket del servidor en caso de pérdida de conexión.
Para enchufes BSD me gustaría consultar la guía de Beej . Cuando recv devuelve 0, se sabe que el otro lado está desconectado.
Ahora es posible que se esté preguntando, ¿cuál es la forma más fácil de detectar la desconexión del otro lado? Una forma de hacerlo es tener un hilo siempre haciendo una grabación. Ese hilo podrá decir instantáneamente cuando el cliente se desconecta.
Puedes llamar a getsockopt como el siguiente:
int error = 0;
socklen_t len = sizeof (error);
int retval = getsockopt (socket_fd, SOL_SOCKET, SO_ERROR, &error, &len);
Para probar si el zócalo está arriba:
if (retval != 0) {
/* there was a problem getting the error code */
fprintf(stderr, "error getting socket error code: %s/n", strerror(retval));
return;
}
if (error != 0) {
/* socket has a non zero error status */
fprintf(stderr, "socket error: %s/n", strerror(error));
}
Tuve un problema similar. Quería saber si el servidor está conectado al cliente o si el cliente está conectado al servidor. En tales circunstancias, el valor de retorno de la función recv puede ser útil. Si el zócalo no está conectado devolverá 0 bytes. Por lo tanto, al usar esto, rompí el bucle y no tuve que usar ningún hilo adicional de funciones. También puede usar este mismo si los expertos creen que este es el método correcto.
get sock opt puede ser algo útil, sin embargo, otra forma sería tener un controlador de señales instalado para SIGPIPE. Básicamente, siempre que se rompe la conexión del socket, el kernel enviará una señal SIGPIPE al proceso y luego podrá hacer lo necesario. Pero esto todavía no proporciona la solución para conocer el estado de la conexión. espero que esto ayude.
puede usar la macro SS_ISCONNECTED
en la función getsockopt()
. SS_ISCONNECTED
se define en socketvar.h
.