2012-05-16 2 views
17

vollständig zu zerstören Ich habe einen Chat-Client in Linux mit Socket gemacht, und ich möchte die Verbindung vollständig zu zerstören. Es folgt die relevanten Teile des Codes:Wie eine Socket-Verbindung in 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; 

aber die Nähe (Socke) scheinen doesnot zu schließen die die Verbindung zerstören, weil nachdem sie vollständig zu ‚Label‘ der Code verlässt die Fehlermeldung zeigt

Unable to bind: Address already in use 

Das ist die Verbindung ist nicht wieder passiert. Was kann das Problem sein? Danke im Voraus.

EDIT: Was ich eigentlich will, ist, wenn ich das Skript von Anfang an nach der Zerstörung der Verbindung laufen, sollte es als ein neues Programm laufen. Wie kann ich es tun?

+0

Warum machst du das? Sie sollten zu kurz vor dem 'accept' zurückkehren, den Server-Socket nicht neu erstellen. – Mat

+0

Warum möchten Sie den hörenden Socket schließen und erneut öffnen, statt sich um accept() 'zu drehen? – dwalter

+0

mögliches Duplikat von [Was ist die Bedeutung von SO_REUSEADDR (Option Setsockopt) - Linux?] (Http://StackOverflow.com/questions/3229860/what-is-the-meaning-of-so-reuseaddr-setsockopt-option- linux) –

Antwort

24

Der Anruf close markiert nur den TCP-Socket geschlossen. Es ist nicht mehr prozessfähig. Aber Kernel kann noch einige Ressourcen für einen Zeitraum (TIME_WAIT, 2MLS usw. Zeug) halten.

Die Einstellung von SO_REUSEADDR sollte Bindungsprobleme entfernen.

So sicher sein, dass der Wert true wirklich nicht Null ist, wenn setsockopt (Überlauf Fehler kann es überschreiben) Aufruf:

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

Es gibt pid Variable Code ist. Wenn Sie fork (zum Starten von Verbindungsbehandlungsverfahren) verwenden, sollten Sie auch sock in dem Prozess schließen, der es nicht benötigt.

-1

Nun, weil eine Verbindung wirklich geschlossen ist, wenn die andere Partei es bestätigt oder nach einer bestimmten Zeitüberschreitung. Dieses Verhalten ist normal ...

EDIT: Ich habe eigentlich nicht, Ihren Code überprüfen, sondern von Kommentaren anderen Nutzer werden Sie etwas falsch zu machen ...

0

Sie sollen den shutdown(2) Systemaufruf verwenden.

+1

Ich habe es versucht, aber immer noch kein Glück. Die Verbindung wird nicht zerstört. –

1

Zuerst für das nameing, so dass wir alle Namen der gleichen Dinge gleich:

Server-Seite:

Die Buchse listen() geführt und dann zu accept() sie die Abhörsocket aufrufen. Der von accept() zurückgegebene Socket nennen wir den akzeptierten Socket.

Client-Seite:

Die Buchse connect() geben wir den Anschluss/verknüpften Buchse rufen.


Ihre Frage in Bezug auf:

die accept() ed Verbindung die akzeptierte Steckdose in der Nähe zu beenden (was Sie verbundenen Anruf), indem zuerst shutdown() von close() gefolgt werden. Um dann eine neue Verbindungsschleife gleich wieder vor dem Anruf zu accept(), nicht zu akzeptieren gehen Sie wieder über bind() und listen().

Nur Abschaltung und den horchenden Socket schließen, wenn Sie von loswerden wollen anhängigeconnect() s, die nach dem accept() zurückgegeben.

1

Die Verbindung ist immer noch aktiv, weil Sie vergessen haben, den angeschlossenen Socket zu schließen. Das Schließen des hörenden Sockets schließt den verbundenen Socket nicht automatisch.

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

Ich bin nicht sicher, obwohl, warum Sie EADDRINUSE bekommen. Der Code funktionierte sowohl auf Linux als auch auf Mac OS.