[sockets]Datenverlust beim verschicken übers Internet
-
Abend an alle,
Ich habe ein Progamm geschrieben ( Linux ) mit dem man belibig grosse daten übers Internet( TCP/IP ) verschicken kann( P2P ).
Soweit läuft alles wunderbar
...Jedoch gibt es ein Problem:
Wenn Daten (bspw eine mp3 datei ) verschickt werden enthält die Datei einige Fehler. Beim anhören z.b gibt es dann ne menge soundfehler ( die ich mir nur mit datenverlust erklären kann
)Werden die Daten nur über 127.0.0.1 oder im internen Netzwerk verschickt, funktioniert alles einwandfrei !
Wie kann ich dafür sorgen, dass alle Daten übers www beim client ankommen ?
PS: Ich kann wenn nötig auch gerne den sourcecode posten !
Gruss darrel

-
Der Source von der Sende- und Empfangs-Routine wäre recht sinnvoll

-
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?
