Socket Programmierung und recv() ist langsam
-
Hallo!
ich lade über Socket und recv eine Datei aus dem Netz (via HTTP). Dabei verwende ich die Funktion recv.
Nun erreicht der Download via Firefox 2Mb/s ich in meiner Funktion aber nur 0,3Mb/s. Ich habe das Gefühl, dass dies unter anderem daran liegt, dass die recv Funktion für nur 5MB 1310720 mal aufgerufen werden muss.
Der Code sieht wie folgt aus:
http://pastebin.com/yUcVshhWMit unterschiedlichen Buffergrößen habe ich schon experimentiert - bringt nichts.
Stefan
-
Mhm, also:
char *buffer = ...
sizeof(buffer) ist hier immer 4, weil buffer ein Zeiger ist, und Zeiger 4 Byte groß sind. Du liest also immer max 4 Byte mit jedem recv.Dann:
if (((float)bytesrec_sum/1024/1024/5) == (float)(bytesrec_sum/1024/1024/5))Diese Bedingung scheint mir immer erfüllt zu sein, wenn ich mich nicht vergucke, steht links von == dasselbe wie rechts, möglicherweise wird hier irgendwas viel zu oft gemacht.
Guck Dir das mal an und teste dann weiter.
-
Hi
Dieser Code ist verdammter Müll !!
Recv ist verdammt schnell ...
Im internen Lan bringe ich Geschwindikeiten von 8-10 MB pro sec + Overhaed.So sollten die Funktionen in etwa aussehen :
long send_data(int socket ,char *sbuf ,long len ) { long rc_2=0; long rc_3=0; long total=0; do { rc_2 = (len - rc_3); // Ganze Len - rc_3 = rc_2 // rc_3 beim 1.t durchlauf 0 rc_3 = send(socket ,&sbuf[rc_3] ,rc_2 ,0); // Bei der send() funktion muss selber if(rc_3==SOCKET_ERROR) { // geprüft werden ob alle Daten des printf("Send Fehler :%i", WSAGetLastError()); // send buffers gesendet wurden. closesocket(socket); // Die anzahl der wirklich gesendeten getchar(); // zeichen kann man aus dem return wert exit(1); // der send funktion entnehmen. } total += rc_3; // Return von rc_3 an total übergeben } while(total!=len); // Wen total ungleich gesamt len dann // schleife widerholen und nicht // gesendete zeichen nach senden return total; } long recv_data(int socket ,char *rbuf ,long len) { long rc_2=0; long rc_3=0; long total=0; do { rc_2 = (len - rc_3); rc_3 = recv(socket ,&rbuf[rc_3] ,rc_2 ,0); if(rc_3==SOCKET_ERROR) { printf("Recv Fehler :%i", WSAGetLastError()); closesocket(socket); getchar(); exit(1); } total += rc_3; } while(total!=len); return total; }Alles Blocking Sockets
lowbyte
-
Hi
Im Lan oder auch nicht kannst du dich jetz an die MTU (Maximum Transmission Unit) heranbewegen für die Packetsize. Ethernet == 1500 byte etc...
So erreichst du riesen Geschwindikeiten.lowbyte
-
Müll!
-
Hi
Ich schrieb:
Im internen Lan bringe ich Geschwindikeiten von 8-10 MB pro sec + Overhaed.Im 100mbit Netz, versteht sich von selbst !
lowbyte
-
Hi
Belli die Funktionen waren nur Bsp. die man Sicher noch verändern muss. Return codes etc...
lowbyte
-
@Belli
völlig richtig:
nach einer Änderung in
char *buffer = char[1024*256];geht es super. Es liegt also wirklich daran, dass er sonst immer nur 4byte ließt.
-
Dein Code ist Müll!
1. stimmt es nicht, daß man beim send über einen blockierten Socket prüfen muß, ob alles versendet wurde (das trifft nur beim recv zu)
2. guck mal genau hin, wohin Dein recv seine Daten in den Puffer schreibt, wenn er mehr als zwei recv's benötigt, um alle Daten zu empfangen.
-
disaster123 schrieb:
@Belli
völlig richtig:
nach einer Änderung in
char *buffer = char[1024*256];geht es super. Es liegt also wirklich daran, dass er sonst immer nur 4byte ließt.
Na bitte, kleine Ursache, große Wirkung

-
-
Hi
Belli schrieb:
Dein Code ist Müll!
1. stimmt es nicht, daß man beim send über einen blockierten Socket prüfen muß, ob alles versendet wurde (das trifft nur beim recv zu)
2. guck mal genau hin, wohin Dein recv seine Daten in den Puffer schreibt, wenn er mehr als zwei recv's benötigt, um alle Daten zu empfangen.
Wenn meinst du damit ? Bei meinem kleinen Bsp. läuft das schon richtig !
lowbyte
-
Hi
Und klar muss man auch bei send() prüfen ob alles gesendet wurde, und wenn nötig nichtgesendete Daten nachsenden.
lowbyte
-
Muß man nicht!
Und Dein recv schreibt in den Puffer ab Stelle rc_3. Was aber steht in rc_3? Die Anzahl der beim letzten recv erhaltenen Bytes.
Wenn der recv nun 3 mal in der Schleife ausgeführt werden sollte und beim ersten Mal 100 Byte und beim zweiten Mal 50 Byte bekommt, wohin schreibt dann der 3. recv seine Daten?
Richtig, er überschreibt die bereits erhaltenen Daten im Puffer!
-
Hi
Nein wenn du es dir nur richtig anschauen wüdest !
lowbyte
-
Und klar muss man auch bei send() prüfen ob alles gesendet wurde
Nein, wenn es sich um einen Blocking Socket unter Windows handelt ist das nicht notwendig. Da gibts nur alles oder nichts.
-
Hi
Ach komm... schau es dir genau an und erzähl nicht so ein Schwachsinn !!
Wen zbsp. 100 bytes empfangen werden sollen, und zbsp. nur 50bytes empfangen werden dan hat rc_3 50 bytes, und das ist dan len - rc_3 = 50bytes und dor schreibt er das nächste mal hin !
lowbyte
-
Hi
() schrieb:
Zitat:
Und klar muss man auch bei send() prüfen ob alles gesendet wurdeNein, wenn es sich um einen Blocking Socket unter Windows handelt ist das nicht notwendig. Da gibts nur alles oder nichts.
Das kann ich nicht bestätigen !
-
Naja ich kann es dafür bestätigen.
Und rc_2, rc_3, das kann ja wohl nur ein Scherz sein.
BTW: Als Puffergrösse die MTU zu verwenden ist doof, die MTU ist viel zu klein für nen anständigen Puffer. Richtig schön grosse Puffer machen, dann geht's auch mit Gigabit noch schön schnell.
-
Hi
Und wen recv() nicht alle daten hat, dan muss man sowiso prüfen wie viele daten jetz noch mit send() gesendet werden sollen.
lowbyte
