[C] HTTP-Server -->> Dateien an Client/Browser senden und anzeigen lassen...



  • Hallo Leute,

    ich hoffe ich bin hier im richtigen Forum.
    Kurz zu mir: Ich bin Programmier-Einsteiger, aber kenne mich gut in den Grundlagen von C aus.
    Momentan beschäftige ich mich mit Servern in C unter Linux.

    Folgendes: Wir haben inzwischen ein primitiven HTTP-Server* programmiert, der eigentlich kaum was kann, außer Verbidnungen annehmen und so weiter...
    Wir wollen jetzt, dass der Server, Dateien auf Anfrage an einen Browser sendet.
    Also, wenn ein User z.B. GET Bild.jpg oder sowas angibt, muss das Bild in dem jeweiligen Ordner auch gefunden und ausgegeben werden.
    Es existiert im Prinzip nur ein Ordner "htdocs" der die Dateien beinhaltet.
    Jetzt kommen wir zum eigentlichen:
    Wie macht man das? Also das Parsen können wir soweit (als Dateiname und Methde Get und so weiter auslesen), aber wie schicke ich nun eine Datei an einem Browser (z.B. Firefox), der mit unserem Server kommuniziert? Wie geht sowas in C? Vor Allem, es können ja belibige Dateien sein, ob nun Textdatei, Bilder oder Videos. Macht man sowas mit HTML-Code oder so?

    * Wir arbeiten an einem PC, sprich wenn wir mit dem Server kommunizieren, nutzen wir im Browser "localhost". Weil wir sind noch am Anfang und wollen uns nur in die Grundlagen und den Aufbau von Servern und so einarbeiten.

    Ich hoffe die Frage klingt nicht dumm, bin neu in diesem Gebiet 😞



  • So sieht übrigens der Server aus, falls das hilft (Code ist in der PDF Datei):

    http://www.file-upload.net/download-7535588/Server.pdf.html

    Die Methoden zum Parsen sind aber noch nicht drin. Das ist jetzt nur unser primitiver Server



  • stichwort: http protokoll, http response header.
    sollten sich brauchbare codeschnipsel finden lassen.

    nützlich kann auch die verwendung von addons/plugins sein, die es z.b. für firefox gibt, die den http datentransfer protokollieren und anzeigen.
    http headers oder so heißt das glaub ich.



  • Dieser Thread wurde von Moderator/in SeppJ aus dem Forum C (C89, C99 und C11) in das Forum Rund um die Programmierung verschoben.

    Im Zweifelsfall bitte auch folgende Hinweise beachten:
    C/C++ Forum :: FAQ - Sonstiges :: Wohin mit meiner Frage?

    Dieses Posting wurde automatisch erzeugt.



  • hi, also erstmal danke für die Antworten.
    Aber ich komme nicht ganz weiter. Ich verstehe immer noch nicht ganz wie die z.b. die Grafik angezeigt werden soll im Browser.
    Ich habe es so gemacht:
    1. Eine Datei geöfnet mit fopen("test.jpg","rb")
    2. die Datei ausgelesen mit fread und in einem Char Array testbuffer gesteckt.
    3. Header erstellt und testbuffer direkt hinterher mitgegeben, also als Body. (natürlich habe ich /r/n nicht vrgessen).

    Aber es klappt nicht. Wenn ich dann per localhost auf den Server zugreife, wird die Meldung angezeigt: "Die Grafik "http://localhost:31337/" kann nicht angezeigt werden, weil sie Fehler enthält."
    Anmerkung: 31337 ist die von mir vergebene Portnummer.

    Wieso klappt das nicht?

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <unistd.h>
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <netinet/in.h>
    
    #define PORT 31337
    #define BUFFER_SIZE 100024
    
    int sockfd;
    struct sockaddr_in serv_addr, cli_addr;
    socklen_t clilen = sizeof(cli_addr);
    
    FILE *pFile;
    char *cfile;
    int filelen;
    
    /**
     * Fehlerbehandlung.
     */
    void error(char *msg) {
    	fprintf(stderr, "%s\n", msg);
    	exit(1);
    }
    
    /**
     * Erstellt und Konfiguriert den Netzwerk-Socket, Ÿber den die Verbindungen
     * angenommen werden.
     */
    void setup_socket() {
    	/*
    	 * Setzt Konfigurationsvariablen fŸr den Socket, z.B. die Portnummer.
    	 */
    	bzero((char *) &serv_addr, sizeof(serv_addr));
    	serv_addr.sin_family = AF_INET;
    	serv_addr.sin_addr.s_addr = INADDR_ANY;
    	serv_addr.sin_port = htons(PORT);
    
    	/*
    	 * Erstelle den Socket.
    	 */
    	sockfd = socket(AF_INET, SOCK_STREAM, 0);
    	if (sockfd < 0)
    		error("ERROR opening socket");
    
    	/*
    	 * Melde, dass der Socket eingehende Verbindungen akzeptieren soll.
    	 */
    	if (bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0)
    		error("ERROR on binding");
    
    	/*
    	 * Horche auf dem Socket nach eingehenden Verbindungen. Es werden maximal
    	 * fŸnf gleichzeitige Verbindungen erlaubt.
    	 */
    	listen(sockfd, 5);
    }
    
    /**
     * Die Hauptschleife, in der eingehende Verbindungen angenommen werden.
     */
    void main_loop() {
    
    	int newsockfd;
    	int length;
    	char buffer[BUFFER_SIZE];
    
    	/*
    	 * Die Hauptschleife des Programms.
    	 */
    	while (1) {
    
    		/*
    		 * Der accept()-Aufruf blockiert, bis eine neue Verbindung rein kommt.
    		 */
    		newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen);
    		if (newsockfd < 0)
    			error("ERROR on accept");
    
    		/*
    		 * Lies die ankommenden Daten von dem Socket in das Array buffer.
    		 */
    		bzero(buffer, sizeof(buffer));
    		length = read(newsockfd, buffer, sizeof(buffer) - 1);
    		if (length < 0)
    			error("ERROR reading from socket");
    
    		sprintf(buffer, "%s\r\n%s\r\n%s\r\n%s\r\n%s%d\r\n\r\n%s",
    				"HTTP/1.1 200 OK", "Location: http://www.trololol.de/",
    				"Content-Type: image/jpeg", "Server: ein server",
    				"Content-Length: ", filelen+1, cfile);
    		length = strlen(buffer);
    		/*
    		 * Schreibe die ausgehenden Daten auf den Socket.
    		 */
    		length = write(newsockfd, buffer, length);
    		if (length < 0)
    			error("ERROR writing to socket");
    
    		/*
    		 * Gib die eingegangenen Daten auf der Kommandozeile aus.
    		 */
    		printf("%s", buffer);
    
    		/*
    		 * Schlie§e die Verbindung.
    		 */
    		close(newsockfd);
    	}
    
    	/*
    	 * Schlie§e den Socket. Dieser Aufruf sollte wegen der Endlosschleife niemals
    	 * ausgefŸhrt werden.
    	 */
    	close(sockfd);
    }
    
    int main(int argc, char *argv[]) {
    
    	pFile = fopen("/home/vbox/Bilder/apfel.jpg", "rb");
    	if(!pFile){
    		return 0;
    	}
    
    	fseek(pFile, 0, SEEK_END);
    	filelen = ftell(pFile);
    	fseek(pFile, 0, SEEK_SET);
    
    	cfile = (char *)malloc(filelen+ 1);
    	if(!cfile){
    		fprintf(stderr, "Memory error!");
    		fclose(pFile);
    		return 0;
    	}
    
    	fread(cfile, filelen, 1, pFile);
    	fclose(pFile);
    
    	setup_socket();
    	main_loop();
    
    	return 0;
    }
    


  • Mach mal Zeilen in deine http-response rein. ("\r\n")



  • Hab ich ja:

    sprintf(buffer, "%s\r\n%s\r\n%s\r\n%s\r\n%s%d\r\n\r\n%s", 
            "HTTP/1.1 200 OK", "Location: http://www.trololol.de/", 
            "Content-Type: image/jpeg", "Server: ein server", 
            "Content-Length: ", filelen+1, cfile);
    


  • Oh ja, das habe ich übersehen. Okay, du versuchst mit sprintf das Bild da rein zu schreiben? Denk da mal drüber nach. 1. Weißt du doch gar nicht ob der Puffer auch groß genug ist. 2. ist ein Bild kein string. (Da sind sicherlich Nullen drin.) 3. ist die Kopie unnötig. Macht einfach zwei send/write Aufrufe, einen für den http-header und einen für das Bild.


Anmelden zum Antworten