Linux下基于http的小型web服务器编写

来源:互联网 发布:新网互联域名证书 编辑:程序博客网 时间:2024/04/30 10:44
#pragma once#include<stdio.h>#include<stdlib.h>#include<string.h>#include<sys/types.h>#include<sys/socket.h>#include<sys/sendfile.h>#include<sys/stat.h>#include<fcntl.h>#include<netinet/in.h>#include<arpa/inet.h>#include<assert.h>#include<pthread.h>#include<errno.h>#define _DEF_PAGE_ "index.html"#define _SIZE_ 1024static void printLog(const char* const str,const char* const fun,int line);void usage(const char*  const  proc);int startup(char* ip,int port);void echo_error(int sock,int errno);int get_line(int sock,char* buf,int size);void clear_head(int sock);void echo_html(int sock,char* path,ssize_t size);void accept_request(int sock);                                                  void* handle_client(void* arg);//http.c#include"http.h"                                                                static void printLog(const char* const str,const char* const fun,int line){    printf("%s:%s:%d\n",str,fun,line);}void usage(const char*  const  proc){    assert(proc);    printLog(proc,__FUNCTION__,__LINE__);}int startup(char* ip,int port){    assert(ip);    int sock=socket(AF_INET,SOCK_STREAM,0);    if(sock<0)    {        printLog(strerror(errno),__FUNCTION__,__LINE__);        exit(1);    }    int opt=1;    setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof(opt));    struct sockaddr_in local;    local.sin_family=AF_INET;    local.sin_port=htons(port);    if(strncmp(ip,"any",3)==0)    {        local.sin_addr.s_addr= INADDR_ANY;    }    else    {        local.sin_addr.s_addr=inet_addr(ip);    }    if(bind(sock,(struct sockaddr*)&local,sizeof(local))<0)    {        printLog(strerror(errno),__FUNCTION__,__LINE__);        exit(1);    }    if(listen(sock,5)<0)    {        printLog(strerror(errno),__FUNCTION__,__LINE__);        exit(1);    }    return sock;}void echoErr(int sock,int errno){    return;}int get_line(int sock,char* buf,int size){    assert(buf);    int i=0;    ssize_t _s=-1;    char ch='\0';//  printf("getLine");    while(i<size-1&&ch!='\n')    {        _s=recv(sock,&ch,1,0);                          if(_s>0)        {            if(ch=='\r')            {                if((_s=recv(sock,&ch,1,MSG_PEEK)))                {                    if(_s>0&&ch=='\n')                        recv(sock,&ch,1,0);                }            }            buf[i++]=ch;        }        else        {            buf[i++]='\n';            break;        }    }//  printf("endddddddddddd");    buf[i]='\0';    return i;}void clear_head(int sock){    char buf[_SIZE_];    buf[0]='\0';    ssize_t _s=1;    while(_s>0&&strcmp(buf,"\n")!=0)    {                                                 _s=get_line(sock,buf,sizeof(buf));    }}void echo_html(int sock,char* path,ssize_t size){//  printf("echo_htmlllllllllll\n");//  printf("path:%s\n",path);    int fd=open(path,O_RDONLY);    if(fd<0)    {        printLog(strerror(errno),__FUNCTION__,__LINE__);        exit(1);    }//  printf("fd:%d\n",fd);    char* status_line="HTTP/1.0  200 ok\r\n\r\n";    send(sock,status_line,strlen(status_line),0);//  printf("sock  success,size:%d\n",size);    if(sendfile(sock,fd,NULL,size)<0)    {        printf("error");    }//  printf("sendfile  success");    close(fd);}void accept_request(int sock){    char buf[_SIZE_];//  int ret;    //  while((ret=get_line(sock,buf,sizeof(buf)))>0)             //  {//      if(ret==0)//      {//          printLog(strerror(errno),__FUNCTION__,__LINE__);//          break;//      }//      printf("%s",buf);//  }    int ret=-1;    int i=0,j=0;    char method[_SIZE_/2];    char url[_SIZE_];    char path[_SIZE_];    memset(method,'\0',sizeof(method));    memset(buf,'\0',sizeof(buf));    memset(path,'\0',sizeof(path));    memset(url,'\0',sizeof(url));    if(get_line(sock,buf,sizeof(buf))==0)    {        printLog("errno",__FUNCTION__,__LINE__);        return;    }//  printf("%s",buf);    i=j=0;    while(!isspace(buf[i])&&i<strlen(buf)&&j<sizeof(method)-1)    {        method[j]=buf[i];//get method                                  ++i;        ++j;    }    method[j]='\0';//  printf("method:%s\n",method);       j=0;    while(isspace(buf[i]))    {        ++i;    }    while(!isspace(buf[i])&&i<strlen(buf)&&j<sizeof(url)-1)    {        url[j]=buf[i];        ++j;        ++i;    }    url[j]='\0';//  printf("url:%s\n",url);    int cgi=0;    if(strcasecmp(method,"POST")!=0&&strcasecmp(method,"GET")!=0)    {        printf("error\n");    //  echoErr(sock,1);        return;    }//  printf("success\n");    if(strcasecmp(method,"POST")==0)    {        cgi=1;                                   }    if(strcasecmp(method,"GET")==0)    {//      printf("getttttttttttttttttttt\n");        char* query_string=url;        while(*query_string!='\0'&&*query_string!='?')        {            ++query_string;        }                                if(*query_string=='?')        {           *query_string='\0';           cgi=1;        }        ++query_string;        sprintf(path,"htdocs%s",url);//sprintf//      printf("path:%s\n",path);        if(path[strlen(path)-1]=='/')        {            strcat(path,_DEF_PAGE_);        }//      printf("cgi=0,path:%s\n",path);        struct stat st;        if(stat(path,&st)<0)//not exist        {            printf("error");            return;                                                       }        else if(S_IFDIR&st.st_mode)//dir        {//          printf("dirrrrrrrrrrr\n");            if(strcmp(path,"htdocs/_DEF_PAGE_")!=0)            {                strcpy(path,"htdocs/");                strcat(path,_DEF_PAGE_);//              printf("hhhhhhhhhhhhhhhhhh");            }        }        else if((st.st_mode&S_IXUSR)||(st.st_mode&S_IXGRP)||(st.st_mode&S_IXOTH))        {//          printf("xxxxxxxxxxxxxxxxxx\n");            cgi=1;        }        if(cgi)        {            //execute_cgi(sock,path,method,query_string);        }        else        {//          printf("echo_html\n");            fflush(stdout);            clear_head(sock);            echo_html(sock,path,st.st_size);        }    }            ​    close(sock);}void* handle_client(void* arg){    int sock=(int)arg;    accept_request(sock);    return NULL;}                       //main.c#include"http.h"                                                                int main(int argc,char* argv[]){    if(argc!=3)    {        usage(argv[0]);        return 1;    }    char* ip=argv[1];    int port=atoi(argv[2]);    int listen_sock=startup(ip,port);    struct sockaddr_in client;    socklen_t len=sizeof(client);    fflush(stdout);    while(1)    {    //  printf("kkkkkkkkkkk");    //  fflush(stdout);        int new_sock=accept(listen_sock,(struct sockaddr*)&client,&len);        if(new_sock<0)        {            printf("no client");            fflush(stdout);            continue;        }        pthread_t id;    //  printf("con");        pthread_create(&id,NULL,handle_client,(void*)new_sock);        pthread_detach(id);//set detach return val:0/errno          }    return 0;}                                    
0 0