Sockets: sauberer verbindungsaufbau
-
sers@ll
ich hab nen socketprogramm geschrieben, und am ende soll ja die verbindung abgebaut werden. das heisst wenn ich das programm beendet habe sollte es danach DIREKT wieder aufruftbar sein
das ist bei mir nicht der fall, ich muss immer erst ca 1 minute warten, bis das programm wieder geht, sonst gibts nur connection refused -> lieg an nem falschen verbindungsabbau.
ich habe mir nochmal die entsprechenden seiten im stevens angeguckt, jede menge rumprobiert, aber ich komme auf kein sauberes ergebnis.
also einer von beiden, der server ODER der client führen ja das close aus. mir ist es egal wer das macht, aber ich krieg keine lösung hin. der server sieht am ende so aus
bind(sockfd, ( struct sockaddr * ) &servaddr, sizeof(servaddr)); listen(sockfd, 1); connfd = accept(sockfd, NULL,NULL); send(connfd,name,sizeof(name),0); while( (bytes = fread(buff,1,sizeof(buff),fd)) > 0) send(connfd,buff,bytes,0); return 0;
letzten relevanten zeilen vom client
while ( (bytes = recv(sockfd,buff, sizeof(buff),0)) > 0) { if(fwrite(buff,1,bytes,fd) == -1 ) { printf("FUCK, couldn write on %s\n",path); perror("Reason"); printf("Going for Disconnect and exit....\n"); fflush(stdout); fclose(fd); close(sockfd); exit(0); } len += bytes; printf("Receiving file....."); printf("\t%d bytes already received\n",len); fflush(stdout); } if ( bytes == -1) { perror("FUCK! recv failed.\nReason"); printf("Going for disconnect and exit....\n"); fclose(fd); close(sockfd); exit(0); } printf("\nEverything is fine, file received\nFile stored at %s\nbytes: %d\n", argv[2],len); printf("%s succesfully downloaded, path: %s\n", name, path); return 0;
also wie muss ich das nun machen, das ein sauberes close durchgeführt wird, die connection sauber beendet wird und das programm direkt wieder benutzt werden kann nachdem server & client beendet sind?
danke!
-
Kann es sein, dass bereits der bind()-Aufruf vom Server fehlschlägt? Solltest mal alle Rückgabewerte überprüfen!
Ich weiß zwar nicht, wieso und warum dass so ist, aber um das zu verhindern musst du dem listenden Socket vor dem bind die Option SO_REUSEADDR geben (mit setsockopt).
-
sers
ne also bind etc geht alles in ordnung, das teil funktioniert ja auch, nur halt alle 30-120 secunden oder so
dein rat mit dem sockopt, meinste das jetzt allgemein das ich das machen soll um mein prob zu verhindern, oder soll ich das machen um deine vermutung zu begradigen?
danke
-
Es ist so, dass man nicht zweimal schnell hintereinander an einen Port binden kann, der Kernel blockiert das dann für eine Zeit (ich glaube irgendwas wegen Sicherheit).
Dafür gibts diese SO_REUSEADDR-Option. Sicher, dass bind() wirklich immer funktioniert? Wie gesagt, Rückgabewert prüfen.
Ansonsten, mehr als close() braucht man eigentlich nicht machen.
-
also am bind kann es ja eigentlich nicht liegen denn:
baue ich am ende des server eine sleep anweisung ein und beende den client nach dem dl, aber vor dem ende, mit strg+c, so kann ich das programm&server direkt danach wieder ausführen, immer wieder
werde das mit der socket option trotzdem mal probieren
-
JETZT PRÜFE DOCH EINFACH DEN RÜCKGABEWERT
Ist doch nur eine Zeile. Wenn es am bind() nicht liegt, kannst du dir das setsockopt auch sparen und brauchst nicht weiter in die Richtung rätseln.
-
ok hast recht
dann werd ich mich nochmal mit den sockoptions auseinander setzen müssen und nochma im stevens blättern, danke für den tipp!
melde mich morgen wieder wenns geklappt hat
-
so es geht jetzt, danke
es lag aber net am port, sondern an der adresse, also SO_REUSEADDR reinhauen. dein riecher war also schon richtig
danke