Error: la dirección ya está en uso al vincular el socket con la dirección, pero `netstat` muestra el número de puerto libre

6 minutos de lectura

avatar de usuario
Durín

Traté de enlazar mi socket (socket del servidor) en el número de puerto 8000. Funcionó e hizo el trabajo por mí. Al final del código también cierro el socket. Al instante siguiente, vuelvo a ejecutar mi código y me muestra que la dirección ya está en uso. He impreso el significado de los valores de error. strerror(errno); para ver si mi código funciona correctamente en cada punto. Para verificar si el puerto está libre, lo verifiqué usando netstat pero muestra ese número de puerto 8000 es gratis. Me ha pasado muchas veces. Cada vez que espero unos segundos más y luego comienza a funcionar nuevamente. Estoy usando lenguaje c. Entonces, ¿cuál es la razón de este comportamiento de mi sistema operativo?

Después de unos segundos más, ejecuto el código y luego funciona.

anirudh@anirudh-Aspire-5920:~/Desktop/testing$ sudo ./a.out 
Socket Creation: Success
File open: Success
Socket Bind: Address already in use
Socket Listen: Address already in use
^C
anirudh@anirudh-Aspire-5920:~/Desktop/testing$ sudo netstat -lntp
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name
tcp        0      0 0.0.0.0:80              0.0.0.0:*               LISTEN      1348/lighttpd   
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      984/sshd        
tcp        0      0 127.0.0.1:631           0.0.0.0:*               LISTEN      1131/cupsd      
tcp        0      0 0.0.0.0:3306            0.0.0.0:*               LISTEN      1211/mysqld     
tcp6       0      0 :::22                   :::*                    LISTEN      984/sshd        
tcp6       0      0 ::1:631                 :::*                    LISTEN      1131/cupsd      
anirudh@anirudh-Aspire-5920:~/Desktop/testing$ sudo ./a.out 
Socket Creation: Success
File open: Success
Socket Bind: Address already in use
Socket Listen: Address already in use
^C
anirudh@anirudh-Aspire-5920:~/Desktop/testing$ 

  • ¿También cierra con cuidado todas las conexiones que se hicieron al servidor mientras se estaba ejecutando?

    – rogerdpack

    11/10/2018 a las 19:45

avatar de usuario
icfantv

Me he encontrado con el mismo problema también. Es porque está cerrando su conexión al socket, pero no al socket en sí. El socket puede entrar en un estado TIME_WAIT (para garantizar que se hayan transmitido todos los datos, TCP garantiza la entrega si es posible) y tarda hasta 4 minutos en liberarse.

o, para una explicación REALMENTE detallada/técnica, mira este enlace

Ciertamente es molesto, pero no es un error. Vea el comentario de @Vereb sobre esta respuesta a continuación sobre el uso de SO_REUSEADDR.

  • hay una posible solución en la página que vinculó. Puede usar la opción SO_REUSEADDR para el socket. ver setsockopt aquí: linux.die.net/man/3/setsockopt

    – verbo

    27/01/2013 a las 14:30

avatar de usuario
Supamee

Sé que ha pasado un tiempo desde que se hizo la pregunta, pero pude encontrar una solución:

int sockfd;
int option = 1;
sockfd = socket(AF_INET, SOCK_STREAM, 0);
setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &option, sizeof(option));

Esto hizo que el zócalo se pueda reutilizar inmediatamente.

Me disculpo si esto es “incorrecto”. no tengo mucha experiencia con enchufes

  • me gusta como te pones wrong entre comillas, lo que implica que cualquiera que no esté de acuerdo contigo está equivocado.

    – byxor

    8 de febrero de 2017 a las 11:29

  • las comillas eran más del tipo “si funciona, no está mal”. Me doy cuenta de que probablemente no sea la forma preferida y si alguien conoce la forma “correcta”, me interesaría saberlo.

    – Supamee

    27/03/2017 a las 14:30

  • que significa el 1

    –Moritz Schmidt

    13 de agosto de 2018 a las 7:22

  • Fue hace un tiempo, así que si me equivoco, corríjame, pero creo que se usa porque cuando desea que el socket no permanezca, debe ser “distinto de cero”. No pude encontrar nada concreto, pero puedes leer más sobre esto en: ibm.com/support/knowledgecenter/en/SSB23S_1.1.0.15/gtpc2/…

    – Supamee

    13 de agosto de 2018 a las 14:01


Prueba netstat así: netstat -ntpsin el -l. Mostrará la conexión tcp en
TIME_WAIT estado.

Como ya se dijo, su socket probablemente ingrese en TIME_WAIT estado. Este problema está bien descrito por Thomas A. Bien aquí.

Para resumir, el proceso de cierre del zócalo sigue el diagrama a continuación:

Proceso de cierre del zócalo

Tomás dice:

Mirando el diagrama de arriba, es claro que TIME_WAIT puede evitarse si el extremo remoto inicia el cierre. Entonces el servidor puede evitar problemas al permitir que el cliente se cierre primero. El protocolo de aplicación debe estar diseñado para que el cliente sepa cuándo cerrar. El servidor puede cerrarse de manera segura en respuesta a un EOF del cliente; sin embargo, también deberá establecer un tiempo de espera cuando esté esperando un EOF en caso de que el cliente haya abandonado la red de forma irregular. En muchos casos bastará con esperar unos segundos antes de que se cierre el servidor.

Utilizando SO_REUSEADDR se sugiere comúnmente en Internet, pero Tomás agregar:

Curiosamente, usando SO_REUSEADDR en realidad puede conducir a errores más difíciles de “dirección ya en uso”. SO_REUSADDR le permite usar un puerto que está atascado TIME_WAIT, pero aún no puede usar ese puerto para establecer una conexión con el último lugar al que se conectó. ¿Qué? Supongamos que elijo el puerto local 1010, me conecto al puerto 300 de foobar.com y luego cierro localmente, dejando ese puerto en TIME_WAIT. Puedo reutilizar el puerto local 1010 de inmediato para conectarme a cualquier lugar excepto a foobar.com puerto 300.

avatar de usuario
programador

Sólo tipo

unlink [SOCKET NAME]

en la terminal, entonces el error ya no debería existir.

  • Eso es para sockets de dominio Unix. La pregunta es sobre los sockets TCP.

    – usuario207421

    1 de julio de 2020 a las 0:54

avatar de usuario
Reloj ZHONG

Incluso la respuesta de icfantv a esta pregunta ya es perfecta, todavía tengo más hallazgos en mi prueba.

Como un socket de servidor en estado de escucha, aunque solo esté en estado de escucha, e incluso acepta solicitudes y obtiene datos del lado del cliente, pero sin ninguna acción de envío de datos. Todavía podríamos reiniciar el servidor inmediatamente después de que se detenga. Pero si ocurre alguna acción de envío de datos en el lado del servidor al cliente, el reinicio del mismo servicio (mismo puerto) tendrá este error: (Dirección ya en uso).

Creo que esto se debe a los principios de diseño de TCP/IP. Cuando el servidor envía los datos al cliente, debe asegurarse de que el envío de datos sea exitoso, para hacer esto, el sistema operativo (Linux) necesita monitorear la conexión, incluso la aplicación del servidor cerró este socket. Pero sigo creyendo que el diseñador de sockets del kernel podría mejorar este problema.

  • Eso es para sockets de dominio Unix. La pregunta es sobre los sockets TCP.

    – usuario207421

    1 de julio de 2020 a las 0:54

avatar de usuario
dr_begemot

Para AF_UNIX puede usar call unlink (ruta); después de cerrar () socket en la aplicación “servidor”

¿Ha sido útil esta solución?

Esta web utiliza cookies propias y de terceros para su correcto funcionamiento y para fines analíticos y para mostrarte publicidad relacionada con sus preferencias en base a un perfil elaborado a partir de tus hábitos de navegación. Al hacer clic en el botón Aceptar, acepta el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Configurar y más información
Privacidad