zoukankan      html  css  js  c++  java
  • 基于C语言的Socket网络编程搭建简易的Web服务器(socket实现的内部原理)

    首先编写我们服务器上需要的c文件WebServer.c

    涉及到的函数API:

      int copy(FILE *read_f, FILE * write_f) ----- 文件内容复制的方法

      int DoHTML(FILE *f, char * name) ------ socket通讯文件发送的重要方法,阐述出了socket编程中的send函数和recv函数的机理!!

      int ParseReq(FILE *f, char *r) -----文件字符串解析的重要方法

      int HandleConnect(int fd)

      void * key(void *data)

      1 #include <stdio.h>
      2 #include <sys/types.h>
      3 #include <sys/socket.h>
      4 #include <netinet/in.h>
      5 #include <stdlib.h>
      6 #include <errno.h>
      7 #include <string.h>
      8 #include <netdb.h>
      9 #include <arpa/inet.h>
     10 #include <unistd.h>
     11 
     12 int KEY_QUIT = 0;
     13 char referrer[128]={0};
     14 int content_length=0;
     15 #define SERVER_PORT 80
     16 static char copybuf[16384]={0};
     17 #define DEBUG 1
     18 
     19 int copy(FILE *read_f, FILE * write_f) //复制文本的API函数copy
     20 {
     21     int n;
     22     int wrote;
     23     n = fread(copybuf,1,sizeof(copybuf),read_f);
     24     wrote = fwrite(copybuf,n,1,write_f);
     25     return 0;
     26 }
     27 
     28 int DoHTML(FILE *f, char * name)
     29 {
     30     FILE *infile;
     31     infile = fopen(name,"r"); //打开本地Client端请求的html文件,文件名为name
     32 
     33     printf("Sending mesg...
    ");
     34     copy(infile,f); //复制Client客户端请求的html文件
     35     printf("Complete sending.
    ");
     36     fread(copybuf,1,sizeof(copybuf),f);
     37     fclose(infile);
     38     return 0;
     39 }
     40 
     41 int ParseReq(FILE *f, char *r) //分析处理请求文件流当中的内容提取请求的文件名index.html
     42 {
     43     char *bp;
     44     char *c;
     45     #ifdef DEBUG
     46     printf("req is %s", r); //请求的内容例如: GET /index.html HTTP/1.1
     47     #endif
     48     while(*(++r) != ' '); //去掉请求内容开头所有的空格部分
     49     while(isspace(*r)) r++; //判断输入字符是否为空格/回车/制表符等,去掉所有的这些字符
     50     while(*r == '/') r++; //去掉所有的'/'字符
     51     bp = r; //得到文件名的起始指针
     52     while(*r && (*r != ' ') && (*r != '?')) r++;
     53     *r = 0;
     54     c = bp;
     55     printf("The Request FileName is %s
    ", c);
     56     DoHTML(f, c); //得到文件名之后处理请求的操作
     57     return 0;
     58 }
     59 
     60 int HandleConnect(int fd)
     61 {
     62     FILE *f;
     63     char buf[160];
     64     f = fdopen(fd, "a+"); //打开对应文件名的html文件
     65     setbuf(f, 0); //清楚f文件缓存区
     66     fgets(buf, 150, f); //从Client端请求中获取前面150个字符
     67     #ifdef DEBUG
     68     printf("buf is %s", buf);
     69     #endif
     70     ParseReq(f, buf); //分析请求的内容
     71     fflush(f); //清空文件缓冲区,将其内容写入文件
     72     fclose(f);
     73     return 1;
     74 }
     75 
     76 void * key(void *data)
     77 {
     78     int c;
     79     for(;;)
     80     {
     81     c = getchar();
     82         if(c == 'q'||c == 'Q')
     83         {
     84         KEY_QUIT = 1;
     85         exit(10);
     86         break;
     87         }
     88     }
     89 }
     90 
     91 int main(int argc, char *argv[])
     92 {
     93     int fd,sockfd;
     94     int len;
     95     volatile int true = 1;
     96     struct sockaddr_in ec;
     97     struct sockaddr_in server_sockaddr;
     98     pthread_t th_key;
     99     printf("Starting httpd...
    ");
    100     printf("press q to quit..
    ");    
    101 
    102     sockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    103     setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR,(void*)&true,sizeof(true));
    104     server_sockaddr.sin_family = AF_INET;
    105     server_sockaddr.sin_port = htons(SERVER_PORT);
    106     server_sockaddr.sin_addr.s_addr = htonl(INADDR_ANY);
    107     bind(sockfd,(struct sockaddr *)&server_sockaddr,sizeof(server_sockaddr));
    108     listen(sockfd,8*3);
    109 
    110     pthread_create(&th_key,NULL,key,0);
    111 
    112     printf("Wait for connection....
    ");
    113     while(1)
    114     {
    115     len = sizeof(ec);
    116         if((fd=accept(sockfd,(void *)&ec,&len)) == -1)
    117         {
    118         exit(0);
    119         close(sockfd);
    120         }
    121     printf("Handle Connection...
    ");
    122         HandleConnect(fd);
    123     }
    124 }

    编写需要的Makefile文件,注意M是大写

    server:WebServer.c
        gcc -o server WebServer.c -lpthread
    clean:
        rm server

    添加我们的html文件,例如取名index.html,文件的内容如下所示:

    <!DOCTYPE html>
    <html>
    <head>
    <title>Welcome to nginx!</title>
    <style>
        body {
            width: 35em;
            margin: 0 auto;
            font-family: Tahoma, Verdana, Arial, sans-serif;
        }
    </style>
    </head>
    <body>
    <h1>Welcome to nginx!This is my first Web Project!Author MM1994UESTC</h1>
    <p>If you see this page, the nginx web server is successfully installed and
    working. Further configuration is required.</p>
    
    <p>For online documentation and support please refer to
    <a href="http://nginx.org/">nginx.org</a>.<br/>
    Commercial support is available at
    <a href="http://nginx.com/">nginx.com</a>.</p>
    
    <p><em>Thank you for using nginx.</em></p>
    </body>
    </html>

    接下来就是运行我们的server文件,主要要使用sudo权限或者root权限来执行server文件:

    sudo ./server

    下面打开浏览器输入对应的主机的IP地址加上文件名称如:192.168.1.125/index.html

     

    完~

  • 相关阅读:
    struts2类型转换
    struts2拦截器
    计算机系统结构
    struts2标签
    struts2 OGNL表达式
    使用bootstrap
    Struts2-综合项目
    拦截器,课3
    struts2之OGNL
    Struts2框架
  • 原文地址:https://www.cnblogs.com/uestc-mm/p/7661750.html
Copyright © 2011-2022 走看看