zoukankan      html  css  js  c++  java
  • C++实现一个web服务器, 弱智版服务器

      监听本地的8888端口, 当在浏览器中访问这个地址的时候, 返回一堆HTML数据, 这种方式返回的数据不稳定,不同浏览器解析不同, 因为我们没有定义返回文件类型:

    #include <stdlib.h>
    #include <stdio.h>
    #include <string.h>
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <netinet/ip.h>
    #include <unistd.h>
    
    int main() {
        int sock = socket(AF_INET, SOCK_STREAM, 0);
        struct sockaddr_in address;
        address.sin_family = AF_INET;
        address.sin_port = htons(8888);
        address.sin_addr.s_addr = inet_addr("192.168.0.58");
        int ret = bind(sock , (const struct sockaddr*)&address , sizeof(address));
        ret = listen(sock, 100);
        printf("lisening..
    ");
    
        struct sockaddr_in client_address;
        socklen_t len;
        int newsock = accept(sock, (struct sockaddr*)&client_address, &len);
        printf("client conneting
    ");
    FILE *fp = fopen("./html/index.html","rb"); char buf[1024] = {0}; fread(buf, 1024, 1, fp); printf("content is %s ", buf); send(newsock, buf, strlen(buf), 0); close(newsock); close(sock); return 0; }

      给服务器的返回设置文件类型和文件大小信息, 避免页面出现乱码和页面的正常解析:

    #include <stdlib.h>
    #include <stdio.h>
    #include <string.h>
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <netinet/ip.h>
    #include <unistd.h>
    
    int main() {
        int sock = socket(AF_INET, SOCK_STREAM, 0);
        struct sockaddr_in address;
        address.sin_family = AF_INET;
        address.sin_port = htons(8888);
        address.sin_addr.s_addr = inet_addr("192.168.1.102");
        int ret = bind(sock , (const struct sockaddr*)&address , sizeof(address));
        ret = listen(sock, 100);
        printf("lisening..
    ");
    
        struct sockaddr_in client_address;
        socklen_t len;
        int newsock = accept(sock, (struct sockaddr*)&client_address, &len);
        printf("client conneting
    ");
    
        //char recvData[1024] ={0};
        //recv(newsock, recvData, sizeof(recvData), 0);
        //printf("receive data:%s", recvData);
        FILE *fp = fopen("./html/index.html","rb");
    
            if( fp == NULL ){
                printf("failed to open img
    ");
           }
        fseek(fp, 0, SEEK_END);
            long fileLen = ftell(fp);
            fseek(fp, 0, SEEK_SET);
        
            char buf[1024] = {0};
            strcat(buf, "HTTP/1.0 200 OK
    ");
            strcat(buf, "Content-Type: text/html;charset=UTF-8
    ");
    
            char contentLength[256] = {0};
            sprintf(contentLength, "Content-Length: %ld
    
    ", fileLen);
            strcat(buf, contentLength);
        
            fread(buf+strlen(buf), 1024, 1, fp);
        send(newsock, buf, strlen(buf), 0);
        close(newsock);
        close(sock);    
        return 0;
    }

      打开本地的PNG图片,并返回给客户端浏览器, 和上面的代码还有一点区别就是, 服务器有返回Content-type和Content-Length :

    #include <stdlib.h>
    #include <stdio.h>
    #include <string.h>
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <netinet/ip.h>
    #include <unistd.h>
    
    int main() {
        int sock = socket(AF_INET, SOCK_STREAM, 0);
        struct sockaddr_in address;
        address.sin_family = AF_INET;
        address.sin_port = htons(8888);
        address.sin_addr.s_addr = inet_addr("192.168.1.102");
        int ret = bind(sock , (const struct sockaddr*)&address , sizeof(address));
        ret = listen(sock, 100);
        printf("lisening..
    ");
    
        struct sockaddr_in client_address;
        socklen_t len;
        int newsock = accept(sock, (struct sockaddr*)&client_address, &len);
        printf("client conneting
    ");
        FILE *fp = fopen("./imgs/img.png","rb");
        if( fp == NULL ){
            printf("failed to open img
    ");
        }
        fseek(fp, 0, SEEK_END);
        long fileLen = ftell(fp);
        fseek(fp, 0, SEEK_SET);
        
        char buf[40960] = {0};
        strcat(buf, "HTTP/1.0 200 OK
    ");
        strcat(buf, "Content-Type: imagepng;charset=UTF-8
    ");
    
        char contentLength[256] = {0};
        sprintf(contentLength, "Content-Length: %ld
    
    ", fileLen);
        strcat(buf, contentLength);
        
        //strlen just string length; but sizeof return all the size;
        fread(buf+strlen(buf), 40960, 1, fp);
        send(newsock, buf, 40960, 0);
        
        close(newsock);
        close(sock);    
        return 0;
    }

        搭建一个服务器:

    /*****************************************************************
    system:kali enviroment:g++ compile command:gcc webServer.c -g -o webServer -lpthread ****************************************************************
    */ #include <stdlib.h> #include <sys/types.h> #include <sys/socket.h> #include <sys/stat.h> #include <netinet/in.h> #include <unistd.h> #include <pthread.h> #include <stdio.h> #include <string.h> #include <arpa/inet.h> #define PORT 8848 #define BACKLOG 5 #define MAXDATASIZE 1000 #define DEBUG 1 void process_cli(int connectfd, sockaddr_in client); int sendobj(int connectfd,char* serverfilepath); int IsDIR(char* fpath); int fileordirExist(char* fpath); char* getextname(char*); void* getHead(char* extname); void* start_routine(void* arg); void msg404(int connectfd); struct ARG { int connfd; sockaddr_in client; }; main() { int listenfd, connectfd; pthread_t thread; //id of thread ARG *arg; //pass this var to the thread struct sockaddr_in server; //server's address info struct sockaddr_in client; //client's int sin_size; //create tcp socket #ifdef DEBUG printf("socket.... "); #endif if ((listenfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) { perror("creating socket failed."); exit(1); } int opt = SO_REUSEADDR; setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)); bzero(&server,sizeof(server)); server.sin_family = AF_INET; server.sin_port = htons(PORT); server.sin_addr.s_addr = htonl(INADDR_ANY); printf("bind.... "); if(bind(listenfd,(struct sockaddr *)&server,sizeof(struct sockaddr)) == -1) { perror("bind error."); exit(1); } printf("listen.... "); if(listen(listenfd,BACKLOG) == -1) { perror("listen() error "); exit(1); } sin_size = sizeof(struct sockaddr_in); while(1) { //accept() using main thread printf("accepting.... "); if((connectfd = accept(listenfd, (struct sockaddr *)&client, (socklen_t*)&sin_size)) == -1) { printf("accept() error "); } arg = new ARG; arg->connfd = connectfd; memcpy((void *)&arg->client, &client, sizeof(client)); //invoke start_routine to handle this thread #ifdef DEBUG printf("thread_creating...."); #endif if(pthread_create(&thread, NULL, start_routine, (void*)arg)){ perror("pthread_create() error"); exit(1); } } close(listenfd); } //handle the request of the client void process_cli(int connectfd, sockaddr_in client) { int num; //char recvbuf[MAXDATASIZE], sendbuf[MAXDATASIZE], cli_name[MAXDATASIZE]; char requestline[MAXDATASIZE], filepath[MAXDATASIZE], cmd[MAXDATASIZE],extname[MAXDATASIZE]; int c; FILE *fp; FILE *cfp; fp = fdopen(connectfd,"r"); #ifdef DEBUG printf("the host is:%s ",inet_ntoa(client.sin_addr) ); #endif fgets(requestline,MAXDATASIZE,fp); #ifdef DEBUG printf(" THE REQUEST IS :%s ",requestline); #endif strcpy(filepath,"./"); sscanf(requestline,"%s%s",cmd,filepath+2); strcpy(extname, getextname(filepath)); #ifdef DEBUG printf("cmd:%s filepath:%s extname:%s ",cmd,filepath,extname); printf("string comparing :::::::::::::start::::::::::::::: "); #endif if(strcmp(cmd,"GET") == 0){ //the command is get #ifdef DEBUG printf("cmd(%s)==GET ",cmd); #endif //is this a file or dir or notexist? printf("filepath is .... : %s ", filepath); if(fileordirExist(filepath)){ //is a file or dir or none //is this a dir if(IsDIR(filepath)){ //is a dir #ifdef DEBUG printf("%s is a DIR ",filepath); #endif if( fileordirExist( strcat(filepath,"index.htm") )){ sendobj(connectfd,"index.htm"); }else if(fileordirExist(strcat(filepath,"index.html"))){ sendobj(connectfd,"index.htm"); }else{ msg404(connectfd); } }else{ //is a file #ifdef DEBUG printf("%s is a file ",filepath); #endif sendobj(connectfd, filepath); } }else{ #ifdef DEBUG printf("404 "); #endif msg404(connectfd); } }else{ #ifdef DEBUG printf("cmd(%s)!=GET ",cmd); #endif } #ifdef DEBUG printf(":::::::::::::end::::::::::::::: "); #endif close(connectfd); } //send the 404 error message to the client void msg404(int connectfd) { char* msg; msg = "HTTP/1.0 404 Not Found Content-Type: text/plain 404 not found by Manio"; send(connectfd,msg,strlen(msg),0); } //is the filepath a file or directory int fileordirExist(char* fpath) { struct stat filestat; return ( stat(fpath,&filestat) != -1); } // is the filepath a directory int IsDIR(char* fpath) { #ifdef DEBUG printf("IN IsDIR "); #endif struct stat filestat; return ( stat(fpath,&filestat) != -1 && S_ISDIR(filestat.st_mode)); } //send the data of the file which the client want int sendobj(int connectfd,char* serverfilepath) { FILE* fp,*cfp; char buf[40960] = {0}; int c; fp = fopen(serverfilepath,"rb"); printf("filepath is %s ", serverfilepath); if( fp == NULL ){ printf("failed to open html file "); } fseek(fp, 0, SEEK_END); long fileLen = ftell(fp); fseek(fp, 0, SEEK_SET); strcat(buf, "HTTP/1.0 200 OK "); strcat(buf, "Content-Type: "); char* fileExt = getextname(serverfilepath); strcat(buf, (char *)getHead(fileExt)); strcat(buf, ";charset=UTF-8 "); char contentLength[256] = {0}; sprintf(contentLength, "Content-Length: %ld ", fileLen); strcat(buf, contentLength); fread(buf+strlen(buf), 40960, 1, fp); printf("buf is %s ", buf); send(connectfd, buf, strlen(buf), 0); return 0; } //write the packet header to the client void* getHead(char* extname) { #ifdef DEBUG printf("INGETHEAD:::::::extname is %s::::::: ",extname); #endif char* content = "text/plain"; if( strcmp(extname,"html") == 0 || strcmp(extname,"htm") == 0) content = "text/html"; else if ( strcmp(extname,"css") == 0 ) content = "text/css"; else if ( strcmp(extname,"gif") == 0 ) content = "image/gif"; else if ( strcmp(extname,"jpeg") == 0 || strcmp(extname,"jpg") == 0) content = "image/jpeg"; else if ( strcmp(extname,"png") == 0) content = "image/png"; return (void *)content; } //get the extent name of the file char* getextname(char* filepath) { char* p; if(( p = strrchr(filepath,'.')) != NULL) return p+1; return NULL; } //invoked by pthread_create void* start_routine(void* arg) { ARG *info; info = (ARG *)arg; process_cli(info->connfd, info->client); delete arg; pthread_exit(NULL); }

      C语言的限制很少..类型可以随便转..系统相对于把所有的权利交给我们了, 所以C语言容易出问题

      C++搭建一个web服务器:http://www.cppblog.com/cuijixin/archive/2008/07/02/55112.html 

  • 相关阅读:
    Javascript小技巧
    VIM
    interview experience
    HTML5
    代码实践
    git clone 速度慢的解决办法
    vscode 找不到相对目录文件的解决办法
    python基础 13 类命名空间于对象、实例的命名空间,组合方法
    python 基础 12 初识类,类方法,类属性
    python 基础 11 带参数装饰器与递归函数
  • 原文地址:https://www.cnblogs.com/diligenceday/p/7087696.html
Copyright © 2011-2022 走看看