[sockets]Datenverlust beim verschicken übers Internet



  • Serverfunktion:

    void Server :: send_data()
    {
    	int sending_status;
    	unsigned long size_pointer = 0;
    	char TCP_packet[TCP_packet_size];
    
    	file_to_send = new char[file_size];
    
    	file_to_send = read_file(file_path, file_size);
    
    	//compute: sending-loop && rest of file (modulo)
    	int sending_counter = file_size / TCP_packet_size; /*************/
    	int rest_of_file = file_size % TCP_packet_size;	  /* 512 bytes */
    
    	//sending loop
    	for ( int i = 0; i <= sending_counter + 1; i++)
    	{
    		//check if end of file is reached
    		if ( i == sending_counter )
    		{
    			TCP_packet_size = rest_of_file;
    		}
    
    		//fill TCP packet
    		for ( int n = 0; n < TCP_packet_size; n++ )
    		{
    			TCP_packet[n] = file_to_send[size_pointer + n];
    		}
    
    		//send packet to client
    		sending_status = send(accepted_socket_id, TCP_packet,
    								  TCP_packet_size, 0); 
    
    		if ( sending_status == -1 )
    		{
    			ERROR("sending data");
    		}
    
    		//add 512 to copy the next 512 bytes of the file
    		size_pointer = size_pointer + 512;
    
    	}
    
    	delete [] file_to_send;
    
    	return;
    }
    

    Clientfunktion: ( dateigrösse wurde davor übertragen )

    void Client :: recive_data_from_host()
    {
    	int reciving_status;
    	char TCP_packet[TCP_packet_size];
    	bool exit = false;
    	unsigned long size_pointer = 0;
    
    	//compute: sending-loop && rest of file (modulo)
    	int reciving_counter = file_size / TCP_packet_size; /*************/
    	int rest_of_file = file_size % TCP_packet_size;	  /* 512 bytes */
    
    	//reciving loop
    	for ( int i = 0; i <= reciving_counter + 1; i++ )
    	{
    		if( i == reciving_counter )
    		{
    			TCP_packet_size = rest_of_file;
    		}
    
    		//recive data from host 
    		reciving_status = recv( socket_id, TCP_packet, TCP_packet_size, 0);
    		if ( reciving_status == -1 )
    		{
    			ERROR("reciving data from host");
    		}
    
    		//assemble file
    		for (int i = 0; i <  TCP_packet_size; i++ )
    		{
    			File_binary[size_pointer + i] = TCP_packet[i];
    		}
    
    		//add 512 to copy the next 512 bytes of the file
    		size_pointer = size_pointer + 512;
    	}
    
    	//wirte data to device 
    	write_file( File_binary, file_size, file_path );
    
    	delete [] File_binary;
    
    	return;
    }
    


  • Du solltest sowohl beim Senden als auch beim Empfangen den Rückgabewert prüfen. Der sagt Dir nämlich, wieviel empfangen und gesendet wurde. Du überprüfst nur, ob irgendwas gesendet (empfangen) wurde und verwirfst (speicherst) dann ein Paket fester Länge.



  • LordJaxom schrieb:

    Du solltest sowohl beim Senden als auch beim Empfangen den Rückgabewert prüfen. Der sagt Dir nämlich, wieviel empfangen und gesendet wurde. Du überprüfst nur, ob irgendwas gesendet (empfangen) wurde und verwirfst (speicherst) dann ein Paket fester Länge.

    THX für den hinweis

    Wäre es dann möglich so mein problem zu beheben ?
    bsp:

    if ( reciving_status != TCP_packet_size )
    { 
           //nochmal gleiches packet senden, solange bis die kompletten 512bytes angekommen sind 
    }
    

    ???

    EDIT: Man müsste quasi dem server jedes mal eine antwort schicken, ob er nochmal senden muss oder ob es mit dem nächsten packet weitergehn kann ?



  • Nein, du solltest eher beim Empfangen nur soviele Bytes nach File_binary schieben, wie du auch empfangen hast und entsprechend auch size_pointer erhöhen 😉



  • Badestrand schrieb:

    Nein, du solltest eher beim Empfangen nur soviele Bytes nach File_binary schieben, wie du auch empfangen hast und entsprechend auch size_pointer erhöhen 😉

    Das ist natürlich die bessere/ elegantere Methode 😃

    Vielen Dank für die Aufklärung !

    Gruss darrell

    EDIT: Aber was ist dann mit den verlorenen packeten ?
    Wenn der Server 512bytes sendet, aber nur bspw 256 ankommen, dann bringt es mit doch wenig die in eine datei zu schreiben.
    Damit wäre ich ja wieder am Anfang des problems.

    Oder kümmert sich die systemfunktion send selbst darum das die packete vollständing übertragen werden ?



  • Wenn der Server 512bytes sendet, aber nur bspw 256 ankommen, dann bringt es mit doch wenig die in eine datei zu schreiben.
    Damit wäre ich ja wieder am Anfang des problems.

    Du checkst das nicht wie TCP/IP funktioniert.
    In dem Fall bekommst du einfach die restlichen 256 Byte später, also beim nächsten mal wo du recv() aufrufst.
    Natürlich kann sein dass dann auch wieder bloss < 256 Bytes ankommen, in dem Fall musst du halt nochmal recv() aufrufen etc.
    Das ist übrigens der #1 Fehler den fast alle Anfänger machen, weil sie die Doku nicht lesen oder nicht verstehen.



  • Beim 2ten Testlauf mit den änderungen sind alle bytes angekommen.

    THX nochmal an alle !!!

    Gruss Darrel



  • und beim 1. testlauf gings nicht? 🙄 🙄



  • kannst ja auch ne funktion schreiben die solange recv in einer schleife ausführt bis genau die anzahl an bytes übertragen wurde... allerdings würde die funktion dann blockieren wenn die gegenseitige nichts mehr sendet..



  • Jetzt läuft deine Kommunikation zwar schon, aber wenn du magst, kannst du dir ja auch mal sfml anschauen, da ist eine recht solide Socket-Library dabei.



  • Badestrand schrieb:

    Jetzt läuft deine Kommunikation zwar schon, aber wenn du magst, kannst du dir ja auch mal sfml anschauen, da ist eine recht solide Socket-Library dabei.

    Hab mir das mal durchgelesen:
    Wenn ich das richtig verstanden hab ist sfml eine c++(also OS unabhängige)libary.
    Wenn das stimmt dann ist es ja möglich mit dieser Lib auf allen systemen mit Sockets zu arbeiten.

    oder liege ich da falsch ?



  • Darrel schrieb:

    Hab mir das mal durchgelesen:
    Wenn ich das richtig verstanden hab ist sfml eine c++(also OS unabhängige)libary.
    Wenn das stimmt dann ist es ja möglich mit dieser Lib auf allen systemen mit Sockets zu arbeiten.

    oder liege ich da falsch ?

    Das hast du richtig erfasst 🙂 Das ist ein großer Vorteil von solchen Libraries, einmal die Plattformunabhängigkeit, zum anderen, dass Bugs meistens recht schnell gefunden und ausgemerzt werden.



  • öhm.. nur mal so als frage ... die SFML müsste doch aber auch auf sockets basieren oder etwa nicht ?



  • Ja, trotzdem sind die socket-Funktionen nicht plattformunabhängig (glaube ich jedenfalls), mindestens aber muss man je nach Plattform verschiedene Header einbinden.



  • ja das stimmt man muss andere header einbinden und unter unix heißt es nicht closesocket sondern close... aber das sind ja geschichten die sich #ifdef usw.. regeln lassen... ich finde solche libs ansich recht praktisch... aber man kann z.b. bei der sfml nicht einsehen wie die funktionen etc aufgebaut sind... dabei lernt man ja nichts... oder kann man iwie sich den quellcode anschauen (lass mich nämlich gerne eines besseren belehren)

    Gruß Chris



  • Dass die Libraries einem die ganzen #ifdef-Geschichten abnehmen, ist doch einer der großen Vorteile. Und ja, SFML ist OpenSource, wenn man sich das Paket runterlädt, sind auch alle Quelltexte dabei (konntest du ja nicht wissen) 🙂



  • danke danke ich werds mir mal ansehen 😉

    GRuß Chris



  • uhm... also wenn schon C++ und Sockets, dann wuerd ich doch eher zu den boost-Sockets raten ( www.boost.org - eine Sammlung vieler Plattformunabhaengiger C++ Funktionen), die SMFL ist ja doch - wie der Name sagt - eher auf Multimedia-Anwendungen ausgerichtet. 🙂



  • uhm... also wenn schon C++ und Sockets

    Ist die Kombination deiner Meinung nach nicht gut? 🙄



  • Stimmt, aber mir persönlich gefallen die SFML-Sockets besser 🙂 Das soll um Himmels Willen kein Totschlagsargument sein, aber ich bin momentan einfach sehr angetan von der SFML. Und dass es eigentlich eine Multimedia-Library ist, heißt ja auch nicht, dass sie andere Sachen nicht kann 😉


Anmelden zum Antworten