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


Anmelden zum Antworten