A tiene el siguiente socket de escucha:
int sd = socket(PF_INET, SOCK_STREAM, 0);
struct sockaddr_in addr;
bzero(&addr, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_port = htons(http_port);
addr.sin_addr.s_addr = INADDR_ANY;
if(bind(sd,(sockaddr*)&addr,sizeof(addr))!=0)
{
...
}
if (listen(sd, 16)!=0)
{
...
}
int sent = 0;
for(;;) {
int client = accept(sd, (sockaddr*)&addr, (socklen_t*)&size);
if (client > 0)
{
...
close(client);
}
}
Si un uso
close(sd);
y luego al intentar recrear el socket con el mismo código, ocurre un error de vinculación, y solo después de 30-60 segundos se crea un nuevo socket con éxito.
¿Hay alguna manera de crear o cerrar de alguna manera genial para evitar el error de vinculación?
En algún lugar del kernel, todavía hay información sobre su socket anterior dando vueltas. Dígale al kernel que está dispuesto a reutilizar el puerto de todos modos:
int yes=1;
//char yes="1"; // use this under Solaris
if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)) == -1) {
perror("setsockopt");
exit(1);
}
Ver la sección bind() en la Guía de programación de redes de beej para una explicación más detallada.
Este es el comportamiento esperado para los sockets TCP. Cuando cierra un socket, pasa al estado TIME_WAIT. Aceptará y descartará paquetes para este puerto. Necesitas configurar el SO_REUSEADDR
opción para enlazar inmediatamente de nuevo.
No debe cerrar el socket enlazado y luego intentar recrearlo.
accept
devuelve un socket recién creado solo para esa conexión, es el que debe cerrarse. es decir: deberías estar haciendo –
close(client);