php in C Webserver implementieren



  • Guten Morgen allerseits,
    falls ich nicht im korrekten Unterforum sein sollte, erstmal sorry dafür.

    Im Rahmen einer Masterarbeit soll folgendes Konzept realisiert werden:

    Ein Webserver soll in C geschrieben werden und selbst erstellte Webseiten bereit stellen können. Da einige Teile in php geschrieben sind, muss php in den Server implementiert werden.

    Ziel ist es letztendlich, dass der C-Code auf einem Microcontroller läuft, und die Webseiten, die zur Konfiguration dienen, von jedem verbundenen Rechner aufgerufen und bearbeitet werden können.

    Quasi ein selbst entwickelter Router...

    Der Server läuft soweit:

    /* httpserv.c
     * Demoprogramm zur Programmierung von Netzwerkservern
     * Es wird ein simpler http Server implementiert,
     * der ausschließlich GET requests bearbeiten kann */
    #include <stdio.h>
    #include <fcntl.h>
    #include <errno.h>
    
    /* Headerfiles für Windows */
    #include <winsock.h>
    #include <io.h>
    
    /* http requests werden normalerweise auf Port 80 
     * vom Server beantwortet */
    #define HTTP_PORT 80
    
    static void serv_request( int in, int out, char* rootpath);
    
    /****************** MAIN *********************/
    int main( int argc, char **argv)
    {
        struct sockaddr_in server, client;
        int sock, fd;
        int len;
    
    #ifdef _WIN32  
        /* Initialisiere TCP für Windows ("winsock") */
        short wVersionRequested;
        WSADATA wsaData;
        wVersionRequested = MAKEWORD (1, 1);
        if (WSAStartup (wVersionRequested, &wsaData) != 0) {
            fprintf( stderr, "Failed to init windows sockets\n");
            exit(1);
        }
    #endif
    
        /* Teste auf Kommadozeilenargument "documentroot" */
        if (2 != argc) {
            fprintf( stderr, "usage: httpserv documentroot\n");
            exit(1);
        }
    
        /* Erzeuge das Socket */
        sock = socket( PF_INET, SOCK_STREAM, 0);
        if (sock < 0) {
            perror( "failed to create socket");
            exit(1);
        }
    
        /* Erzeuge die Socketadresse des Servers 
         * Sie besteht aus Typ und Portnummer */
        memset( &server, 0, sizeof (server));
        server.sin_family = AF_INET;
        server.sin_addr.s_addr = htonl( INADDR_ANY);
        server.sin_port = htons( HTTP_PORT);
    
        /* Erzeuge die Bindung an die Serveradresse 
         * (d.h. an einen bestimmten Port) */
        if (bind( sock, (struct sockaddr*)&server, sizeof( server)) < 0) {
            perror( "can't bind socket");
            exit(1);
        }
    
        /* Teile dem Socket mit, dass Verbindungswünsche
         * von Clients entgegengenommen werden */
        listen( sock, 5);
    
        /* Bearbeite die Verbindungswünsche von Clients 
         * in einer Endlosschleife
         * Der Aufruf von accept() blockiert solange, 
         * bis ein Client Verbindung aufnimmt */
        for (;;) {
            len = sizeof( client);
            fd = accept( sock, (struct sockaddr*)&client, &len);
            if (fd < 0) {
                perror( "accept failed");
                exit(1);
            }
    
            /* Bearbeite den http Request */
            serv_request( fd, fd, argv[1]);
            /* Schließe die Verbindung */
            closesocket( fd);
        }
    }
    
    /*
     * serv_request
     * Bearbeite den auf in ankommenden http request
     * Die zu sendenden Daten werden auf out ausgegeben
     */
    static void serv_request( int in, int out, char* rootpath)
    {
        char buffer[8192];
        char *b, *l, *le;
        int count, totalcount;
        char url[256];
        char path[256];
        int fd;
        int eoh = 0;
    
        b = buffer;
        l = buffer;
        totalcount = 0;
        *url = 0;
        while ( (count = recv( in, b, sizeof(buffer) - totalcount, 0)) > 0) {
            totalcount += count;
            b += count;
            while (l < b) {
                le = l;
                while (le < b && *le != '\n' && *le != '\r') ++le;
                if ('\n' == *le || '\r' == *le) {
                    *le = '\0';
                    printf ("Header line = \"%s\"\n", l);
                    sscanf( l, "GET %255s HTTP/", url);
                    if (strlen(l)) eoh = 1;
                    l = le + 1;
                }
            }
            if (eoh) break;
        }
    
        if ( strlen(url)) {
            printf( "got request: GET %s\n", url);
            sprintf(path, "%s/%s", rootpath, url); 
            fd = open( path, O_RDONLY);
            if (fd > 0) {
                sprintf( buffer, "HTTP/1.0 200 OK\nContent-Type: text/html\n\n");
                send( out, buffer, strlen(buffer), 0);
                do {
                    count = read( fd, buffer, sizeof(buffer));
                    send( out, buffer, count, 0);
                    printf(".");
                    fflush(stdout);
                } while (count > 0);
                close( fd);
                printf("finished request: GET %s\n", url);
            }
            else {
                sprintf( buffer, "HTTP/1.0 404 Not Found\n\n");
                send( out, buffer, strlen(buffer), 0);
            }
        }
        else {
            sprintf( buffer, "HTTP/1.0 501 Method Not Implemented\n\n");
            send( out, buffer, strlen(buffer), 0);
        }
    }
    

    allerdings werden die php-Seiten noch nicht richtig angezeigt. Gibt es eine Möglichkeit, php so in den C-Code einzubinden?

    Danke für Antworten


  • Mod

    PHP ist hier eine sehr schlechte Idee.
    Python oder Lua wären gängiger.

    Für PHP solltest du dir mal PH7 ansehen: http://ph7.symisc.net/

    Und ich würde den Server auch nicht komplett selber schreiben, es gibt mongoose, das ist ein HTTP/HTTPS Server in C, den du in deine Anwendung einbetten kannst: http://code.google.com/p/mongoose/



  • Da kann ich mich Shade Of Mine auch anschließen. Selbst einen Server schreiben ist nicht so trivial, wie es auf den ersten Blick aussieht. Ein kurzer Blick in den Code offenbart gleich ein paar Fehler. Mindestens einer ist eine Sicherheitsissue (eine Url wie /../../../etc/passwd wird akzeptiert). Ganz abgesehen von deniel of service Problemen.



  • Hab mir mal lua angeschaut, sieht ganz vernünftig aus.

    Zudem bin ich auf cgi gestoßen, was für mich auf den ersten Blich zweckorientierter erscheint.

    Nun muss ich meinen Server so umbauen, dass ich auch cgis ausführen kann.

    Hat das jemand schon mal gemacht oder kann mir gerade einer auf die Sprünge helfen wie ich das am besten implementiere?

    Grüße


  • Mod

    CGI ist simpel:
    Du startest einen externen Prozess und setzt in dessen Kontext die von CGI definierten Umgebungsvariablen.

    Aber mach es einfach mit Lua direkt in deiner Anwendung - ist viel simpler und schneller.



  • Das hab ich soweit verstanden. Allerdings finde ich zu cgi nur Beispiele mit Webservern wie z.B. Apache, der cgi unterstützt. Daher such ich einen Code den ich in meinen Quelltext einbetten kann.

    Zu Lua: die Syntax ist wirklich sehr simpel, was mir aber bei meinem Problem nicht wirklich weiter hilft.

    Angenommen ich habe eine html-Seite in die eine Eingabe gemacht wird, ein Login z.B., bei dem nur ein Passwort eingegeben werden muss (wie beim Router). Wenn ich diese Eingabe nun auslese, kann ich sie dann mit Lua in den C-Code übergeben? (Wichtig für die spätere Parametrierung des zu steuernden Gerätes)

    Grüße



  • Stutzpeter schrieb:

    Das hab ich soweit verstanden. Allerdings finde ich zu cgi nur Beispiele mit Webservern wie z.B. Apache, der cgi unterstützt. Daher such ich einen Code den ich in meinen Quelltext einbetten kann.

    Wie wäre es mit "selber programmieren"? Programmieren besteht normalerweise nicht aus copy&paste.



  • Der gute alte Standard-Rat für Menschen, die einem zu faul erscheinen...

    da ich Elektrotechnik studiere, liegt der Schwerpunkt der Arbeit nicht auf der Programmiererei. Da solche Sachen definitiv schon existieren, wäre es für mich recht unsinnig, das Rad neu zu erfinden, sonst bekäme ich ein immenses Zeitproblem. Daher bin ich leider auf externe Hilfe in diesem Bereich angewiesen...

    Also falls jemand einen Codeschnipsel ganz selbstlos zur Verfügung stellen könnte, würde ich mich sehr freuen...



  • Stutzpeter schrieb:

    Also falls jemand einen Codeschnipsel ganz selbstlos zur Verfügung stellen könnte, würde ich mich sehr freuen...

    da sich dir mit sicherheit auch noch keine frau einfach so 'selbstlos zur Verfügung' gestellt hat, stehen die chancen dafür eher schlecht 👎



  • da ich Elektrotechnik studiere, liegt der Schwerpunkt der Arbeit nicht auf der Programmiererei.

    zum glück, denn du hast da in deine 100 zeilen so eine menge fehler eingebaut, dass mir bei dem gedanken an eine nach außen zugängliche schnittstelle ganz anders wird 😮



  • programmversteher schrieb:

    da ich Elektrotechnik studiere, liegt der Schwerpunkt der Arbeit nicht auf der Programmiererei.

    zum glück, denn du hast da in deine 100 zeilen so eine menge fehler eingebaut, dass mir bei dem gedanken an eine nach außen zugängliche schnittstelle ganz anders wird 😮

    Danke für den Hinweis, aber wieso wirst du nicht konkret und verrätst mir, wo die Fehler liegen, und wie man sie behebt? Ich dachte immer, dafür sei ein Forum da...

    Ich verstehe generell die abwertende Haltung gegenüber Menschen, die hier einen Thread eröffnen "Wie knacke ich Facebook Passwörter, schreibt mir einen Code!"
    Allerdings ist dies bei mir nicht der Fall.



  • Stutzpeter schrieb:

    Ich dachte immer, dafür sei ein Forum da...

    nö, das ist falsch. im grunde geht es in foren nur um die schwanzlänge. und die mit den langen hacken auf den mit den kleinen rum 😋 🙄 😞



  • micropenis schrieb:

    Stutzpeter schrieb:

    Ich dachte immer, dafür sei ein Forum da...

    nö, das ist falsch. im grunde geht es in foren nur um die schwanzlänge. und die mit den langen hacken auf den mit den kleinen rum 😋 🙄 😞

    Was ja auch verständlich ist, jeder mag es, sich an einem Gefühl der Pseudo-Macht zu laben. Mir scheint, hier werden sie nicht geholfen... 😞



  • mir scheint du hast schon alle antworten bekommen. ich weiß ja auch nicht, warum du in einer embedded umgebung php starten willst. aber hey, auch dafür hast du eine antwort bekommen.

    so, ich werd mich schnell aufreiben duschen und dann husch husch nen pfeil machen 😃 ➡


  • Mod

    Schau dir mal zB das hier an: http://linux.die.net/man/2/execve

    Du startest einen Prozess und setzt dort bestimmte Umgebungsvariablen.



  • Stutzpeter schrieb:

    Danke für den Hinweis, aber wieso wirst du nicht konkret und verrätst mir, wo die Fehler liegen, und wie man sie behebt? Ich dachte immer, dafür sei ein Forum da...

    Einen Fehler habe ich ja schon mal angedeutet. Und ich habe ja auch gesagt, dass es nicht trivial ist, einen Webserver zu implementieren. Die Details würde dieses Forum ein wenig sprengen. Daher empfehle ich, einen existierenden zu nehmen. Es gibt sehr viele Webserver. Da ist sicher auch einer dabei, der Deinen Anforderungen genügt.

    Gerade als Elektrotechniker willst Du Dich ja nicht mit den Details rum plagen sondern willst ein konkretes Problem lösen. Und das ist nicht, einen Webserver zu schreiben.



  • das ist richtig, deswegen bin ich gerade dabei mich mit dem mongoose anzufreunden...
    Hoffe auf den Beginn einer wunderbaren Freundschaft 😃


Anmelden zum Antworten