2012-05-16 9 views
17

He creado un cliente de chat en Linux usando socket, y deseo destruir la conexión por completo. A continuación se presenta las partes pertinentes del Código:Cómo destruir por completo una conexión de socket en C

int sock, connected, bytes_recieved , true = 1, pid; 
char send_data [1024] , recv_data[1024];  
struct sockaddr_in server_addr,client_addr;  
int sin_size; 
label: 
if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1) 
{ 
    perror("Socket"); 
    exit(1); 
} 
if (setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,&true,sizeof(int)) == -1) 
{ 
    perror("Setsockopt"); 
    exit(1); 
} 
server_addr.sin_family = AF_INET;   
server_addr.sin_port = htons(3128);  
server_addr.sin_addr.s_addr = INADDR_ANY; 
bzero(&(server_addr.sin_zero),8); 
if (bind(sock, (struct sockaddr *)&server_addr, sizeof(struct sockaddr))== -1) 
{ 
    perror("Unable to bind"); 
    exit(1); 
} 
if (listen(sock, 5) == -1) 
{ 
    perror("Listen"); 
    exit(1); 
} 
printf("\nTCPServer Waiting for client on port 3128"); 
fflush(stdout); 
connected = accept(sock, (struct sockaddr *)&client_addr,&sin_size); 
//necessary code 
close(sock); 
goto label; 

pero la estrecha (calcetín) parecen doesnot para cerrar el destruir la conexión por completo, porque después de ir al 'etiqueta' el código está saliendo que muestra el mensaje de error

Unable to bind: Address already in use 

Esa es la conexión no está ocurriendo de nuevo. Cuál puede ser el problema? Gracias por adelantado.

EDITAR: Lo que realmente quiero es que, cuando ejecuto el script desde el principio después de destruir la conexión, debería ejecutarse como un programa nuevo. ¿Cómo puedo hacerlo?

+0

¿Por qué estás haciendo eso? Debería regresar a justo antes del 'aceptar', no volver a crear el socket del servidor. – Mat

+0

¿Por qué quiere cerrar y volver a abrir el socket de escucha en lugar de dar vueltas alrededor de 'accept()'? – dwalter

+0

posible duplicado de [¿Cuál es el significado de SO_REUSEADDR (opción setsockopt) - Linux?] (Http://stackoverflow.com/questions/3229860/what-is-the-meaning-of-so-reuseaddr-setsockopt-option- linux) –

Respuesta

24

La llamada close solo marca el socket TCP cerrado. Ya no se puede usar por proceso. Pero kernel todavía puede contener algunos recursos por un período (cosas de TIME_WAIT, 2MLS etc.).

El ajuste de SO_REUSEADDR debería eliminar los problemas de enlace.

así que asegúrese de que el valor de true es muy distinto de cero cuando se llama a setsockopt (error de desbordamiento puede sobrescribir):

true = 1; 
setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,&true,sizeof(int)) 

No es pid variable es su código. Si usa fork (para iniciar procesos de manejo de conexión), entonces debe cerrar sock también en el proceso que no lo necesita.

-1

Bueno, porque una conexión está realmente cerrada cuando la otra parte lo reconoce o después de un tiempo de espera determinado. Este comportamiento es normal ...

EDIT: Yo en realidad no comprobar su código pero a partir de los comentarios de otros usuarios, que está haciendo algo mal ...

0

Se debe utilizar la llamada shutdown(2) sistema.

+1

Lo he intentado pero todavía no tuve suerte. La conexión no está siendo destruida. –

1

En primer lugar para la nameing, por lo que todos los nombres de las mismas cosas de la misma: laterales

Servidor:

La toma pasaron a listen() y luego a accept() vamos a llamar el socket de escucha. El socket devuelto por accept() llamemos al socket aceptado.

lado del cliente:

El enchufe pasado a connect() vamos a llamar a la toma de conexión/conectado.


En cuanto a su problema:

para terminar la conexión accept() ed cerrar el conector aceptado (lo que llamamos conectado) usando primero seguido de shutdown()close(). Para aceptar un nuevo bucle de conexión volver antes de la llamada a accept(), no ir a través de bind() y listen() otra vez.

Solo apague y cierre la toma de audición si desea deshacerse de pendiente s emitido después de accept() devuelto.

1

La conexión sigue activa porque se olvidó de cerrar el conector conectado. Cerrar la toma de audición no cierra automáticamente la toma conectada.

//necessary code 
close(connected); // <---- add this line 
close(sock); 
goto label; 

No estoy seguro de por qué a pesar de que está recibiendo EADDRINUSE. El código funcionó bien tanto en Linux como en Mac OS.

Cuestiones relacionadas