Consulta este enlace
http://www.toptip.ca/2010/02/linux-eaddrnotavail-address-not.html
EDITAR :Sí, quería agregar más, pero tuve que cortarlo allí debido a una emergencia
¿Cerró el enchufe antes de intentar volver a conectarlo? El cierre le dirá al sistema que el par de sockets (ip/puerto) ahora está libre.
Aquí hay elementos adicionales que también puede consultar:
- Si el puerto local ya está conectado a la IP remota y al puerto dados (es decir, ya hay un par de enchufes idénticos), recibirá este error (vea el enlace del error a continuación).
- Asociar una dirección de socket que no sea la local generará este error. si las direcciones IP de una máquina son 127.0.0.1 y 1.2.3.4, y está intentando vincular a 1.2.3.5, obtendrá este error.
- EADDRNOTAVAIL:la dirección especificada no está disponible en la máquina remota o el campo de dirección de la estructura del nombre es todo ceros.
Enlace con un error similar al tuyo (la respuesta está cerca de la parte inferior)
http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4294599
Parece que su socket está básicamente atascado en uno de los estados internos de TCP y que agregar un retraso para la reconexión podría resolver su problema como parece haberlo hecho en ese informe de errores.
Si no está dispuesto a cambiar la cantidad de puertos temporales disponibles (como sugirió David), o si necesita más conexiones que el máximo teórico, existen otros dos métodos para reducir la cantidad de puertos en uso. Sin embargo, son violaciones en varios grados del estándar TCP, por lo que deben usarse con cuidado.
El primero es activar SO_LINGER
con un tiempo de espera de cero segundos, forzando el TCP
stack para enviar un paquete RST y vaciar el estado de la conexión. Sin embargo, hay una sutileza:debe llamar a shutdown
en el descriptor de archivo de socket antes de close
, para que tengas la oportunidad de enviar un FIN
paquete antes del RST
paquete. Entonces el código se verá así:
shutdown(fd, SHUT_RDWR);
struct linger linger;
linger.l_onoff = 1;
linger.l_linger = 0;
// todo: test for error
setsockopt(fd, SOL_SOCKET, SO_LINGER,
(char *) &linger, sizeof(linger));
close(fd);
El servidor solo debería ver un restablecimiento prematuro de la conexión si FIN
el paquete se reordena con el RST
paquete.
Consulte la opción TCP SO_LINGER (cero), cuando sea necesario, para obtener más detalles. (Experimentalmente, no parece importar dónde configura setsockopt
.)
El segundo es usar SO_REUSEADDR
y un bind
explícito (incluso si usted es el cliente), lo que permitirá que Linux reutilice los puertos temporales cuando se ejecute, antes de que terminen de esperar. Tenga en cuenta que debe usa bind
con INADDR_ANY
y puerto 0
, de lo contrario SO_REUSEADDR
no se respeta Su código se verá algo como:
int opts = 1;
// todo: test for error
setsockopt(fd, SOL_SOCKET, SO_REUSEADDR,
(char *) &opts, sizeof(int));
struct sockaddr_in listen_addr;
listen_addr.sin_family = AF_INET;
listen_addr.sin_port = 0;
listen_addr.sin_addr.s_addr = INADDR_ANY;
// todo: test for error
bind(fd, (struct sockaddr *) &listen_addr, sizeof(listen_addr));
// todo: test for addr
// saddr is the struct sockaddr_in you're connecting to
connect(fd, (struct sockaddr *) &saddr, sizeof(saddr));
Esta opción es menos buena porque aún saturará las estructuras de datos internas del kernel para las conexiones TCP según netstat -an | grep -e tcp -e udp | wc -l
. Sin embargo, no comenzará a reutilizar los puertos hasta que esto suceda.
Esto también puede suceder si se proporciona un puerto no válido, como 0.