Socket.h - unvollständiges Empfangen von HTML-Dateien via Webserver



  • Hallo,

    ich versuche seit 2-3 Tagen dieses simple Programm zu erstellen, welches lediglich eine Website via das HTTP empfangen soll.
    Leider fehlen bei der Übertragung der Beispielseite die letzten paar Zeichen (ca. 100-300 Stück).

    #include <iostream.h>
    
    //Für Methode 2 (siehe unten)
    //#include <string.h>
    
    #include <sys/socket.h>
    #include <netdb.h>
    
    int main(void)
    {
    	int IDSocket = socket(AF_INET, SOCK_STREAM, 0);
    
    	if(IDSocket > 0)
    	{
    		struct sockaddr_in sa;
    			sa.sin_family	= AF_INET;
    			sa.sin_addr	= *((struct in_addr *)gethostbyname("www.aldinator.de")->h_addr);
    			sa.sin_port	= htons(80);
    			sa.sin_zero[8];
    		if(connect(IDSocket, (const struct sockaddr *)&sa, sizeof(sa))==0)
    		{
    			char request[] = "GET /tipps.htm HTTP/1.1\nHost: www.aldinator.de\n\n";
    
    			if(send(IDSocket, (const void *)request, sizeof(request), 0))
    			{
    				int length = 0;
    				char buffer[1024];
    
    				//Methode 3 (Letzte versuchte Methode)
    				while((length = recv(IDSocket, (void *)buffer, sizeof(buffer), 0)))
    				{
    					cout << buffer;
    				}
    				cout << '\n';
    				//Methode 2
    				/*do
    				{
    					length = recv(IDSocket, (void *)buffer, 1024, 0);
    					cout << length << '\n' << buffer;
    				} while(strpbrk(buffer, "\n\n") == NULL);*/
    				//Methode 1
    				/*while((length = recv(IDSocket, (void *)buffer, 1024, 0))>0)
    				{
    				cout << '\n' << length << ":\n" << buffer << '\n';
    				cout << "length: " << length;
    				}*/
    			}
    			else
    			{
    				close(IDSocket);
    				cout <<  "Error 4: Failed to send request.\n";
    				return 4;
    			}
    
    			close(IDSocket);
    			return 0;
    		}
    		else
    		{
    			close(IDSocket);
    			cout << "Error 2: Failed to connect to server.\n";
    			return 2;
    		}
    	}
    	else
    	{
    		cout << "Error 1: Failed to create socket.\n";
    		return 1;
    	}
    }
    

    1. Warum wird das Dokument nicht komplett empfangen?
    2. Warum erhalte ich via recv(...) abwechselnd 1024 bzw. 416 Zeichen, nicht wie von mir erwartet dauerhaft 1024 Zeichen?

    Vielen Dank im Voraus,
    Sebastian Behrens

    PS: Ich hoffe, dass das Linux/Unix Forum richtig ist, da es unter Windows kein <sys/socket.h> gibt. Falls ich mich Irre, bitte ich um Verzeihung.



  • Kein Wunder...

    Sorry war etwas zu schnell:
    Die Anzahl der gelesenen Bytes werden als bool intepretiert
    und 1023 ist true und deine Zahl im letzten Block wohl nicht...

    Gruß,
    CSpille

    PS: Ich dachte schon du hast nen ähnliches Problem wie ich 😉



  • Hi Cspille,

    vielen Dank für deine schnelle Antwort, leider verstehe ich sie nicht ganz.

    Meinst du, dass das '-1' in dieser Zeile

    while((length = recv(IDSocket, (void *)buffer, sizeof(buffer)-1, 0)))
    

    nicht korrekt ist? Ich habe diese Form in einem Beispielquelltext im Internet gefunden und es aus lauter Verzweiflung ausprobiert. Ohne das '-1' funktioniert es auch nicht.

    Falls ich deine Antwort falsch interpretiert habe, korrigiere mich bitte.

    Um unnötige Missverständnisse vorzubeugen: Nicht bei jedem einzelnen übertragenen 1024-Bit Block fehlt das letzte Bit, sondern der letzte Block (also die letzten 1-1024 Zeichen) werden nicht übertragen!

    Mit freundlichen Grüßen,
    Sebastian Behrens



  • 0-Terminierung vergessen.

    while((length = recv(IDSocket, buffer, sizeof(buffer) - 1, 0)))
    {
        buffer[length] = '\0';
        cout << buffer;
    }
    


  • Der Ausdruck:

    (length = recv(IDSocket, (void *)buffer, sizeof(buffer)-1, 0))
    

    liefert ja einen int...

    1024 bzw. 424
    Diese Zahl interpretiert er als bool...
    (dachte ich --- wahrscheinlich ist nur 0 false)
    Denn bei mir geht er immer in die Bedingung...

    Kuck dir deine Ausgabe nochmal an...
    Er gibt nach dem ausgelesenen String natürlich auch noch den Rest des Puffers aus.
    Er liest die ganze Seite, nur ist dahinter noch jede Menge Müll...

    🙂

    Aber der String ist wirklich nicht terminiert...
    Solltest du auf jeden Fall machen
    (deswegen mußt du auch -1 machen wegen der Null-Terminierung)

    Gruß,
    CSpille

    Achso:
    Ich würde aber trotzdem auf <=0 überprüfen,
    sonst kommst aus der Schleife nicht mehr raus
    (Das funct aber nur, wenn der Server die Connection killt,
    was er bei deiner Anfrage machen sollte)



  • Es funktioniert!
    Vielen Dank an euch Beide!

    Ich Dummkopf bin am Anfang davon ausgegangen, dass die Null-Terminierung von recv(...) automatisch in den Buffer geschrieben wird, und habe dann nicht daran gedacht!

    Die Fehler an denen man sehr lange sitzt sind nicht selten sehr trivial! 🙄

    Danke!

    Mit freundlichen Grüßen,
    Sebastian Behrens


Anmelden zum Antworten