zoukankan      html  css  js  c++  java
  • A LinuxJunky Blog: A Very Simple HTTP Server writen in C

    A Linux-Junky Blog: A Very Simple HTTP Server writen in C

    A Very Simple HTTP Server writen in C

    This is a part of the semester assignment. I felt like sharing it because I couldnt find any simple code like this on internet..



    I have just edited the code to meet my requirements, originally it was made by my friend.. This code simply creates a web server with root in the current working directory and default port as 10000..

    Can handle a maximum of 1000 clients.. fork() is used to handle each clients. Not a very efficient way if the number of clients increase but its a basic example to how you how to implement a simple HTTP Server.











    /*
    AUTHOR: Abhijeet Rastogi (http://www.google.com/profiles/abhijeet.1989)
    
    This is a very simple HTTP server. Default port is 10000 and ROOT for the server is your current working directory..
    
    You can provide command line arguments like:- $./a.aout -p [port] -r [path]
    
    for ex.
    $./a.out -p 50000 -r /home/
    to start a server at port 50000 with root directory as "/home"
    
    $./a.out -r /home/shadyabhi
    starts the server at port 10000 with ROOT as /home/shadyabhi
    
    */
    
    #include<stdio.h>
    #include<string.h>
    #include<stdlib.h>
    #include<unistd.h>
    #include<sys/types.h>
    #include<sys/stat.h>
    #include<sys/socket.h>
    #include<arpa/inet.h>
    #include<netdb.h>
    #include<signal.h>
    #include<fcntl.h>
    
    #define CONNMAX 1000
    #define BYTES 1024
    
    char *ROOT;
    int listenfd, clients[CONNMAX];
    void error(char *);
    void startServer(char *);
    void respond(int);
    
    int main(int argc, char* argv[])
    {
        struct sockaddr_in clientaddr;
        socklen_t addrlen;
        char c;   
       
        //Default Values PATH = ~/ and PORT=10000
        char PORT[6];
        ROOT = getenv("PWD");
        strcpy(PORT,"10000");
    
        int slot=0;
    
        //Parsing the command line arguments
        while ((c = getopt (argc, argv, "p:r:")) != -1)
            switch (c)
            {
                case 'r':
                    ROOT = malloc(strlen(optarg));
                    strcpy(ROOT,optarg);
                    break;
                case 'p':
                    strcpy(PORT,optarg);
                    break;
                case '?':
                    fprintf(stderr,"Wrong arguments given!!!\n");
                    exit(1);
                default:
                    exit(1);
            }
       
        printf("Server started at port no. %s%s%s with root directory as %s%s%s\n","\033[92m",PORT,"\033[0m","\033[92m",ROOT,"\033[0m");
        // Setting all elements to -1: signifies there is no client connected
        int i;
        for (i=0; i<CONNMAX; i++)
            clients[i]=-1;
        startServer(PORT);
    
        // ACCEPT connections
        while (1)
        {
            addrlen = sizeof(clientaddr);
            clients[slot] = accept (listenfd, (struct sockaddr *) &clientaddr, &addrlen);
    
            if (clients[slot]<0)
                error ("accept() error");
            else
            {
                if ( fork()==0 )
                {
                    respond(slot);
                    exit(0);
                }
            }
    
            while (clients[slot]!=-1) slot = (slot+1)%CONNMAX;
        }
    
        return 0;
    }
    
    //start server
    void startServer(char *port)
    {
        struct addrinfo hints, *res, *p;
    
        // getaddrinfo for host
        memset (&hints, 0, sizeof(hints));
        hints.ai_family = AF_INET;
        hints.ai_socktype = SOCK_STREAM;
        hints.ai_flags = AI_PASSIVE;
        if (getaddrinfo( NULL, port, &hints, &res) != 0)
        {
            perror ("getaddrinfo() error");
            exit(1);
        }
        // socket and bind
        for (p = res; p!=NULL; p=p->ai_next)
        {
            listenfd = socket (p->ai_family, p->ai_socktype, 0);
            if (listenfd == -1) continue;
            if (bind(listenfd, p->ai_addr, p->ai_addrlen) == 0) break;
        }
        if (p==NULL)
        {
            perror ("socket() or bind()");
            exit(1);
        }
    
        freeaddrinfo(res);
    
        // listen for incoming connections
        if ( listen (listenfd, 1000000) != 0 )
        {
            perror("listen() error");
            exit(1);
        }
    }
    
    //client connection
    void respond(int n)
    {
        char mesg[99999], *reqline[3], data_to_send[BYTES], path[99999];
        int rcvd, fd, bytes_read;
    
        memset( (void*)mesg, (int)'\0', 99999 );
    
        rcvd=recv(clients[n], mesg, 99999, 0);
    
        if (rcvd<0)    // receive error
            fprintf(stderr,("recv() error\n"));
        else if (rcvd==0)    // receive socket closed
            fprintf(stderr,"Client disconnected upexpectedly.\n");
        else    // message received
        {
            printf("%s", mesg);
            reqline[0] = strtok (mesg, " \t\n");
            if ( strncmp(reqline[0], "GET\0", 4)==0 )
            {
                reqline[1] = strtok (NULL, " \t");
                reqline[2] = strtok (NULL, " \t\n");
                if ( strncmp( reqline[2], "HTTP/1.0", 8)!=0 && strncmp( reqline[2], "HTTP/1.1", 8)!=0 )
                {
                    write(clients[n], "HTTP/1.0 400 Bad Request\n", 25);
                }
                else
                {
                    if ( strncmp(reqline[1], "/\0", 2)==0 )
                        reqline[1] = "/index.html";        //Because if no file is specified, index.html will be opened by default (like it happens in APACHE...
    
                    strcpy(path, ROOT);
                    strcpy(&path[strlen(ROOT)], reqline[1]);
                    printf("file: %s\n", path);
    
                    if ( (fd=open(path, O_RDONLY))!=-1 )    //FILE FOUND
                    {
                        send(clients[n], "HTTP/1.0 200 OK\n\n", 17, 0);
                        while ( (bytes_read=read(fd, data_to_send, BYTES))>0 )
                            write (clients[n], data_to_send, bytes_read);
                    }
                    else    write(clients[n], "HTTP/1.0 404 Not Found\n", 23); //FILE NOT FOUND
                }
            }
        }
    
        //Closing SOCKET
        shutdown (clients[n], SHUT_RDWR);         //All further send and recieve operations are DISABLED...
        close(clients[n]);
        clients[n]=-1;
    }
  • 相关阅读:
    UITableViewCell隔行换颜色
    NSUserDefaults数据保存使用
    使用API获取(默认付款条件和到期日)
    分类账和法人实体
    如何避免Oracle Form界面倒入.csv文件出现乱码
    XML publisher 填充空白行数
    DBA处理异常常用SQL
    wsh_deliveries_pub.create_update_delivery异常
    sql
    破解Oracle ERP密码
  • 原文地址:https://www.cnblogs.com/lexus/p/2596819.html
Copyright © 2011-2022 走看看