Http - Client



  • Hallo,
    muss bis Montag folgende lösen. Wäre also über eine schnelle Antwort froh 😃

    7.2: Rewrite the HTTP client program to enable it to download .gif and .jpg files. Use a separate thread for downloading each file.

    Habe den Code schon geschrieben, die datei wird aber nur zur hälfte runtergeladen.(ca. 4700 Bytes statt 9121 Bytes)

    Hier kommt der Code:

    #include <unistd.h>
    #include <stdlib.h>
    #include <stdio.h>
    #include <string.h>
    #include <signal.h>
    #include <pthread.h>
    
    extern int	errno;
    
    int	errexit(const char *format, ...);
    int	connectTCP(const char *host, const char *service);
    int 	processhtml(char *html);
    void	*getimage(void *arg);
    static void timeoutexit(int sig);
    
    #define	LINELEN		128
    #define ERRORCODE	"200 OK"
    #define HTMLBEGIN	"<"
    #define IMGBEGIN	"<img src"
    #define IMGSOURCE	"src=\""
    
    char *host = "www.google.de";
    char *site = "/";
    char *service = "http";
    
    int
    main(int argc, char** argv)
    {
    	signal(SIGALRM, timeoutexit);
    	alarm(120);
    	connectServer(host, service, site);
    	exit(0);
    }
    
    connectServer(const char *host, const char *service, const char *site)
    {
    	int	s, n;   /* socket, read count		*/
    	char	buf[LINELEN+1];  /* buffer for one line of text	*/
    	char	string[120];
    	char 	*html=NULL;
    
    	s = connectTCP(host, service);
    	sprintf(string,"GET http://%s HTTP/1.0\n\r\n\r",host);
    	write(s, string, sizeof(string));
    	while( (n = read(s, buf, LINELEN)) > 0)
    	{
    		buf[n] = '\0';  /* ensure null-terminated	*/
    		if (!html){
    		    html = (char*) malloc(sizeof(buf));
    		} else {
    		    html = (char*) realloc(html,strlen(html)+sizeof(buf));
    		}
    		strcat(html, buf);
    	}
    	if (strstr(html,ERRORCODE)){
    	   html = strstr(html,HTMLBEGIN);
    	   processhtml(html);
    	} else
    	{
    	  printf("Unknown error!\n");
    	}
    }
    
    static void timeoutexit(int sig){
      printf("Timeout!\n");
      exit(0);
    }
    
    int processhtml(char *html){
    
    char 	*img;
    char 	*sub;
    int 	i;
    int 	tc=0;
    pthread_t *t=NULL;
    
      while ((html = strstr(html,IMGBEGIN)) != NULL) {
        sub = (char*) malloc(255);
        img = (char*) malloc(255);
        img = strncpy(img,html,strcspn(html,">"));
        html += strlen(img);
        img = strstr(img,IMGSOURCE);
        img = img + 5;
        sub = strncpy(sub,img,strcspn(img,"\""));
        t = (pthread_t*) realloc(t,sizeof(pthread_t)*tc+1);
        pthread_create(&t[tc++],NULL,getimage,sub);
      }
       for(i=0;i<tc;i++){
       pthread_join(t[i],NULL);
       }
      return 0;
    }
    
    void *getimage(void *arg){
    
    int 	s, n;    /* socket, read counter */
    char	string[120];
    char	buf[LINELEN+1];  /* buffer for one line of text	*/
    FILE 	*fileptr;
    char	*image=arg;
    char    name[30];
    char *  datei = NULL;
    
      s = connectTCP(host,service);
      sprintf(string,"GET %s HTTP/1.0\n\r\n\r",image);
    
      write(s, string, sizeof(string));
      image = strstr(image,"/");
      image = image + 1;
      fileptr = fopen("image.gif","w+");
    
      while( (n = recv(s, buf, LINELEN,0)) > 0) {
    	if (!datei){
    		    datei = (char*) malloc(sizeof(buf));
    		} else {
    		    datei = (char*) realloc(datei,strlen(datei)+sizeof(buf));
    		}
    		strcat(datei, buf);
      }
      fprintf(fileptr,"%s",datei);
      fclose(fileptr);
    exit(0);
    }
    


  • Wieviel zahlst du?



  • if (!datei){
                datei = (char*) malloc(sizeof(buf));
            } else {
                datei = (char*) realloc(datei,strlen(datei)+sizeof(buf));
            }
            strcat(datei, buf);
    

    mit strlen() und strcat() wirds nichts bei einer .gif datei.
    Kurt



  • Danke für die schnelle Antwort. Problem besteht aber weiterhin obwohl ich strcat & strlen ersetzt habe.

    while( (n = read(s, buf, LINELEN)) > 0) {
    	buf[n] = '\0';		/* ensure null-terminated	*/
    	(void) fputs( buf, fileptr );
      }
    

    Gruß
    Sebastian



  • Das wird auch nichts. Deine daten ( .jpeg, .gif ) enthalten '\0' dann funktionieren stringfungtionen nicht.
    check out memmove(), memcpy()
    Kurt



  • Danke für den Tip. Bin gerade dabei das in Ordnung zu bringen.
    Ich habe mit Etheral den Netzverkehr verfolgt und der Server sendet alle 9120 Bytes. Der Client quittiert auch den Empfang. Nur die am Ende vom Client erstellte Datei ist nur 5000 Byte groß.
    Weist du woran es ligen könnte?

    Sebastian



  • Klar. Du verwendest strlen() ( auch fputs() verwendet intern strlen()) um die daten zu kopieren. => beim ersten '\0' in den Daten hörts auf.
    Du musst fwrite() zum speichern der Daten verwenden. ( Mein Hinweis auf memmove war weil ich geglaubt habe du willst die Daten im Speicher halten).
    so sollte es gehen

    while( (n = read(s, buf, LINELEN)) > 0) {
        fwrite( buf, 1, n, fileptr );
      }
    

    Kurt



  • Habe jetzt mehr Bytes als nötig 🙂 Was mache ich falsch.

    Hier was ich geändert habe:

    while( (n = read(s, buf, LINELEN)) > 0)
      {
    	fwrite(buf,1,LINELEN,fileptr);
      }
    

    Sebastian



  • Vielleicht öffnest du fileptr im textmode ?
    Kurt



  • 😃
    Hab die Antwort zu spät gelesen
    sebastian



  • FILE *fileptr;

    fileptr = fopen("image.gif","w+");



  • Ich habs! Ich speichere ja noch den http-header mit. Muss noch ein weg finden den wegzukriegen.



  • du schreibst LINELEN bytes, obwohl du nur n bytes schreiben solltest.

    im uebrigen heisst es \r\n\r\n statt \n\r\n\r



  • Danke, hast mich der Lösung näher gebracht. Aber es sind immer noch 200 Bytes zuviel. 😞

    Der HTTP Header wird immer noch mitgespeichert.

    Hier ein Auszug der Datei:

    HTTP/1.0 200 OK^M
    Content-Type: image/gif^M
    Last-Modified: Mon, 25 Apr 2005 21:07:03 GMT^M
    Expires: Sun, 17 Jan 2038 19:14:07 GMT^M
    Server: GWS/2.1^M
    Content-Length: 9121^M
    Date: Sat, 03 Dec 2005 23:28:06 GMT^M
    Connection: Keep-Alive^M
    ^M
    GIF89a-^An^@ç^@^@ÿÿÿ÷...................Dateikauderwelsch
    

    Hab schon alles mögliche probiert,weiss aber nicht wie ich den wegbekomme.
    Sebastian



  • der header hoert nach dem ersten \r\n\r\n auf. nach der markierung suchst du und speicherst nur den rest.



  • Welche Fkt. würdest du nutzen um dieses \r\n\r\n zu finden?

    Habs mit memmem versucht, hat aber nicht geklappt. 😞

    while( (n = read(s, buf, LINELEN)) > 0)
      {
      	if(found = 0)
    	{
      		tmp = (char *)memmem(buf,sizeof(buf),"\r\n\r\n",4);
    		if(tmp != NULL)
    		{
    			fwrite(tmp,1,n,fileptr);
    			found =1;
    		}
    	}
    	else
    				fwrite(tmp,1,n,fileptr);
      }
    


  • > Welche Fkt. würdest du nutzen um dieses \r\n\r\n zu finden?
    dein memmem() find ich ausgezeichnet geeignet. kannte die funktion vorher noch garnicht.

    > ...hat aber nicht geklappt.
    inwiefern?

    in deinem code wuerde ich es so machen:

    fwrite(tmp+4, 1, n - (4 + (int)(tmp-buf)), fileptr);
    

    +4 fuer \r\n\r\n
    und "n-..." als korrektur fuer die laenge.

    soll das if (found=0) beabsichtigt eine zuweisung sein?



  • Hab keine Ahunng ob hinter dem File noch etwas gesendet wird aber im Header steht ja das Feld Content-Length also vielleicht geht
    Anfang = GesammtLänge - ContentLength ( ok das funktioniert nur wenn du das komplette File in den Speicher liest ).
    Ausserdem ist der Header ist ja sowieso Text also müsste strstr() auch funktionieren.
    Kurt



  • Aber es ist nicht sichergestellt das das \r\n\r\n an einem Stück kommt.



  • Hab versucht die Datei komplett in den Speicher zu laden. Die Datei ist aber nicht in Ornung.
    Hier ein Auszug:

    !áʯ^T˱$˲?¯°^LK³T˵^L?~@^@^@^@^@^@^@^@^@^@^@^@^@^..............
    

    Vermute das es am strcat liegt, weiss aber kein anderen weg buf an den bisher eingelesenen Speicher(tmp) anzuhängen. Hab strncpy schon mit memcpy ersetzt, daran liegt es nicht, das die Datei so ausschaut.

    int cnt = 0;
      while( (n = read(s, buf, LINELEN)) > 0)
      {
    	    if (!tmp){
    		    tmp = (char*) malloc(n);
    		} else {
    		    tmp = (char*) realloc(tmp,cnt+n);
    		}
    	cnt=cnt+n;
    	tmp2=malloc(cnt);
    	strcat(tmp2,buf);
    	strncpy(tmp,tmp2,cnt-1);
      }
    fwrite(tmp,1,cnt,fileptr);
    


  • Wie gesagt stringfunktionen funktionieren definitiv nicht. memcpy funktioniert. Du brauchst aber etwas Zeigerarithmetik.
    Kurt


Anmelden zum Antworten