programming - sockets cpp
Error: La dirección ya está en uso mientras se vincula el socket con la dirección pero el número de puerto se muestra gratis con `netstat` (8)
Como ya se dijo, su socket probablemente ingrese en el estado TIME_WAIT
. Este problema está bien descrito por Thomas A. Fine here .
Para resumir, el proceso de cierre de socket sigue el siguiente diagrama:
Thomas dice:
Mirando el diagrama de arriba, está claro que
TIME_WAIT
puede evitarse si el extremo remoto inicia el cierre. Por lo tanto, el servidor puede evitar problemas al permitir que el cliente cierre primero. El protocolo de la aplicación debe estar diseñado para que el cliente sepa cuándo cerrar. El servidor puede cerrarse de forma segura en respuesta a un EOF del cliente, sin embargo, también deberá establecer un tiempo de espera cuando se espera un EOF en caso de que el cliente haya abandonado la red de forma descortés. En muchos casos, simplemente esperar unos segundos antes de que el servidor se cierre será suficiente.
El uso de SO_REUSEADDR
se sugiere comúnmente en Internet, pero Thomas agrega:
Curiosamente, el uso de
SO_REUSEADDR
puede llevar a errores más difíciles de "dirección ya en uso".SO_REUSADDR
permite utilizar un puerto que está bloqueado enTIME_WAIT
, pero todavía no puede usar ese puerto para establecer una conexión con el último lugar al que se conectó. ¿Qué? Supongamos que escojo el puerto local 1010 y me conecto al puerto 300 de foobar.com y luego me cierro localmente, dejando ese puerto enTIME_WAIT
. Puedo reutilizar el puerto local 1010 de inmediato para conectarme a cualquier lugar, excepto al puerto 300 defoobar.com
.
Traté de enlazar mi socket (socket del servidor) en el puerto número 8000
. Funcionó e hizo el trabajo por mí. Al final del código también cierro el socket. El siguiente instante corro mi código nuevamente 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 es libre lo comprobé usando netstat
pero muestra que el número de puerto 8000
es gratis. Me ha sucedido muchas veces. Cada vez que espero unos segundos más y luego vuelve a funcionar. Estoy usando el lenguaje c Entonces, ¿cuál es la razón de este comportamiento por mi sistema operativo?
Después de algunos 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$
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, si solo está en estado de escucha, e incluso acepta solicitudes y obtención de datos del lado del cliente, pero sin ninguna acción de envío de datos. Todavía podemos reiniciar el servidor de una vez después de que se detenga. Pero si ocurre alguna acción de envío de datos en el lado del servidor para el cliente, el mismo reinicio del servicio (mismo puerto) tendrá este error: (Dirección ya en uso).
Creo que esto es causado por los principios de diseño de TCP / IP. Cuando el servidor envía los datos al cliente, debe garantizar el éxito del envío de los datos. Para ello, el sistema operativo (Linux) necesita supervisar la conexión incluso si la aplicación del servidor cerró este socket. Pero todavía creo que el diseñador de socket kernel podría mejorar este problema.
Me he encontrado con el mismo problema también. Es porque está cerrando su conexión al zócalo, pero no al zócalo en sí. El socket puede ingresar al estado TIME_WAIT (para garantizar que todos los datos se hayan transmitido, TCP garantiza la entrega si es posible) y demorar hasta 4 minutos para su lanzamiento .
o, para una explicación REALMENTE detallada / técnica, verifique este enlace
Puede ser molesto, pero no hay forma de evitarlo y no es un error.
Para AF_UNIX puede usar desvincular llamada (ruta); después de cerrar () socket en la aplicación "servidor"
Pruebe netstat de la siguiente manera: netstat -ntp
, sin el -l
. Mostrará la conexión tcp en el estado TIME_WAIT
.
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 establece el socket capaz de ser reutilizado de inmediato.
Me disculpo si esto es "incorrecto". No tengo mucha experiencia con enchufes
Sólo tipo
unlink [SOCKET NAME]
en la terminal, entonces el error ya no debería existir.
el error que recibí fue:
cockpit.socket: Failed to listen on sockets: Address already in use
la solución que descubrí es:
- Tuve que deshabilitar selinux
en el servicio / usr / lib / systemd / system / cockpit cambié la línea:
#ExecStartPre=/usr/sbin/remotectl certificate --ensure --user=root --group=cockpit-ws --selinux-type=etc_t
a:
#ExecStartPre=/usr/sbin/remotectl certificate --ensure --user=root --group=cockpit-ws
para que pueda ver, saqué la discusión sobre Selinux y luego ejecuté:
systemctl daemon-reload
systemctl start cockpit.service
luego busqué:
Acepté el certificado autofirmado y pude iniciar sesión con éxito en el puesto de pilotaje y usarlo normalmente.
esto es todo en una máquina fedora25. el puerto 9090 ya se había agregado usando firewall-cmd