C++ UDP Datei senden
-
Hey Leute.
Ich arbeite an einem UDP Client Server Projekt.
Dazu gehört selbstredend auch ein Dateitransfer.
Ich habe gehört, dass die Datei dazu in 64k Blöcke (wenn ich es richtig verstanden habe 65536 Byte Blöcke) geteilt und versandt.
Der Server empfängt dann diese 64k Blöcke und schreibt sie in eine Datei.Dieses System funktoniert auch soweit, nur bei ca. 1,5 MB großen Dateien kommen einige Blöcke nicht an.
Hat jemand eine Idee, was optimiert werden könnte, etc.?
Bei Codeschnipseln fragt bitte, wollte erstmal nicht den Thread mit dem gesamten Code voll spammen.Mit freundlichen Grüßen
DerCoder
-
Das hat nichts mit C++ zutun.
Bei UDP ist ein Ankommen der Daten nicht garantiert, da musst du dich selbst drum kümmern.
-
Was meinst du mit selbst drum kümmern?
-
Wenn ein Paket unterwegs verschwindet, dann ist es halt dein Problem. TCP garantiert dir durch schlaue Verfahren, dass ein gesendet Paket auch ankommt.
-
Hmm, also wäre TCP in diesem Falle klüger?
-
DerCoder schrieb:
Hmm, also wäre TCP in diesem Falle klüger?
Kurze Antwort: Ja.
Längere: Man könnte sich auch selbst mit UDP ein Protokoll basteln, welches zum Beispiel durch gegenseitige Bestätigungspakete die Zustellung einer Nachricht sicherstellt. Verbindungen sollte man auch noch einbauen. All das kann TCP schon.
-
Okay, vielen Dank
-
TyRoXx schrieb:
Bei UDP ist ein Ankommen der Daten nicht garantiert, da musst du dich selbst drum kümmern.
Die Reihenfolge wird auch nicht garantiert. Paket 2 kann eher ankommen als Paket 1. UDP Pakete sollten auch nicht zu groß sein, Stichwort MTU. Die werden dann meines Wissens nach ggf fragmentiert, einzeln versandt. Wenn es ein Fragment nicht "schafft" ist das ganze UDP-Paket verloren.
-
Hm also.
Ich bin jetzt auf TCP umgestiegen, die Datei kommt jedoch immernoch nicht vollständig an. 196608 Bytes gingen verloren (1306745 von 1503353).
Ich habe sogar eingebaut, dass immer, wenn ein Paket ankommt, eine kurze Nachricht zurück geschickt wird. Danach wird erst weiter gemacht.
Klappt leider nicht. Wo kann jetzt noch der Fehler liegen?MFG DerCoder
-
ähhh ich weiß nicht?
Sollen wir jetzt raten oder was?
Zeig mal code her
-
Vom Server oder vom Client?
-
DerCoder schrieb:
Ich bin jetzt auf TCP umgestiegen [...] Ich habe sogar eingebaut, dass immer, wenn ein Paket ankommt, eine kurze Nachricht zurück geschickt wird. Danach wird erst weiter gemacht. [...]
Auf Nutzerseite gibt es bei TCP keine Pakete. Da hat man mit Datenströmen zu tun. Bei TCP muss man sich auch keine Sorgen darum machen, dass etwas nicht ankommt. Das ist ja gerade der Witz an TCP. Wenn Du selbst noch jedes Datenhäppchen quittieren willst, bevor Du ein neues schickst, wirst Du aus Latenzgründen eine sehr schlechte Datenrate bekommen.
Du wirst irgendwo nen Bug in Deinem Programm haben -- hat auch wieder nichts mit C++ zu tun.
-
Okay. Nur eine Frage.
Wie kann es sein, dass nur 3 Pakete ankommen, egal welche "Blockgröße" ich vorziehe?
Client (Sender):DWORD WINAPI sr_sendFile (LPVOID pParam) { // Variablen deklarieren printf ("thread started\n"); cl_funcs cl; int intFileSize = 0;; char charFileSize[128]; int bytesSent = 0; sendFilePart = true; // Datei öffnen, Länge berechnen ifstream fileIn ("c:\\LKS.exe", ios::binary); fileIn.seekg (0, ios::end); intFileSize = fileIn.tellg (); fileIn.seekg (0, ios::beg); itoa (intFileSize, charFileSize, 10); // Bereitschaftsbefehl senden cl.sendMessage ("?!", 2); printf ("go ready sent\n"); Sleep (1000); cl.sendMessage (charFileSize, strlen (charFileSize)); printf ("size sent ... continue with file\n"); while (!fileIn.eof ()) { char buffer[MAX_MESSAGE_SIZE]; fileIn.read (buffer, sizeof (buffer)); while (!sendFilePart) { Sleep (1); } cl.sendMessage (buffer, fileIn.gcount ()); sendFilePart = false; bytesSent += fileIn.gcount (); printf ("%i\tbytes sent\n", bytesSent); //Sleep (100); } fileIn.close (); return 0; }
Server (Empfänger):
char temp[16384]; int rc; //cout <<inet_ntoa(from.sin_addr) <<":"<<temp<<"\r\n"; rc = recv (sRecSocket, temp, sizeof (temp), 0); if (rc > 0) { temp[rc] = '\0'; string msg (temp); for (;;) { if (recFileStatus == 0) { if (msg == "?!") { printf ("?! received\n"); recFileStatus = 1; } printf("Client hat folgendes gesandt: %s\n", temp); break; } if (recFileStatus == 1) { recFileSize = atoi (temp); recFileStatus = 2; printf ("size set to: %i\n", recFileSize); fileOut.open ("D:\\out.exe", ios::app | ios::binary); break; } if (recFileStatus == 2) { fileOut.write (temp, rc); fileOut.flush (); recFileReceived += rc; float percentage = recFileReceived / recFileSize; printf ("%i\t%i\t%f\n", recFileReceived, recFileSize, percentage); send(sRecSocket,"np",2,0); break; } } return 0; }
Wenn der Server np sendet, dann wird beim Client der Bool sendFilePart auf true gesetzt.