Debe seguir los siguientes pasos para una conexión asíncrona:
- crear socket con
socket(..., SOCK_NONBLOCK, ...)
- iniciar conexión con
connect(fd, ...)
- si el valor devuelto no es
0
niEINPROGRESS
, luego cancelar con error - espera hasta
fd
se señala como listo para la salida - verifique el estado del socket con
getsockopt(fd, SOL_SOCKET, SO_ERROR, ...)
- hecho
Sin bucles, a menos que desee manejar EINTR
.
Si el cliente se inicia primero, debería ver el error ECONNREFUSED
en el último paso. Si esto sucede, cierre el zócalo y comience desde el principio.
Es difícil saber qué está mal con su código, sin ver más detalles. Supongo que no abortas por errores en tu check_socket
operación.
Hay algunas formas de probar si una conexión sin bloqueo tiene éxito.
- llame primero a getpeername(), si falló con el error ENOTCONN, la conexión falló. luego llame a getsockopt con SO_ERROR para obtener el error pendiente en el socket
- llamar a read con una longitud de 0. si la lectura falló, la conexión falló y el errno para read indica por qué falló la conexión; read devuelve 0 si la conexión tiene éxito
- llamar a conectar de nuevo; si el errno es EISCONN, la conexión ya está conectada y la primera conexión se realizó correctamente.
Ref:Programación en Red UNIX V1
D. J. Bernstein reunió varios métodos para verificar si un connect()
asíncrono llamada exitosa o no. Muchos de estos métodos tienen inconvenientes en ciertos sistemas, por lo que escribir código portátil para eso es inesperadamente difícil. Si alguien quiere leer todos los métodos posibles y sus inconvenientes, consulte este documento.
Para aquellos que solo quieren la versión tl;dr, la forma más portátil es la siguiente:
Una vez que el sistema señale el socket como escribible, primero llame a getpeername()
para ver si se conecta o no. Si esa llamada tuvo éxito, el enchufe se conectó y puede comenzar a usarlo. Si esa llamada falla con ENOTCONN
, la conexión falló. Para averiguar por qué falló, intente leer un byte del socket read(fd, &ch, 1)
, que también fallará, pero el error que obtiene es el error que habría obtenido de connect()
si no fuera sin bloqueo.