基于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

 

完~

原文地址:https://www.cnblogs.com/uestc-mm/p/7661750.html