1. 程式人生 > >基於HTTP協議的web伺服器專案

基於HTTP協議的web伺服器專案

專案簡介: 基於 HTTP 協議實現一個多執行緒伺服器,客戶端通過瀏覽器傳送請求,伺服器接收並分析客戶端的請求方法和資源,從而執行相應的邏輯處理,最終將客戶請求的資源以 HTML 頁面的形式呈現,並能進行差錯處理。 專案思路: 首先實現兩個主機不同程序間的通訊,當伺服器收到請求後,要進行分析請求方法,當方法確定後應該拿到請求的資源,接下來要根據資源是否存在執行相應的邏輯處理。GET 方法:如果沒有引數,進入非 cgi 模式執行;否則,進入 cgi 模式執行;只要是 POST 方法就一定要支援 cgi:直接進入 cgi 模式執行。 專案特點: 1、支援客戶端/伺服器模式,客戶端能夠使用 GET、POST 方法請求資源; 2、簡單快速:客戶向伺服器請求服務時,只需傳送請求方法和路徑; 3、靈活:HTTP 允許傳輸任意型別的資料物件,正在傳輸的型別由 Content-Type 加以標記。

專案所包含目錄: sql_connect wwwroot lib

http.c程式碼

  1 #include<stdio.h>
  2 #include<string.h>
  3 #include<unistd.h>
  4 #include<fcntl.h>
  5 #include<stdlib.h>
  6 #include<ctype.h>
  7 #include<sys/stat.h>
  8 #include<sys/socket.h>
  9 #include<netinet/in.h>
 10 #include<arpa/inet.h>
 11 #include<sys/sendfile.h>
 12 #include<pthread.h>
 13 
 14 #define MAX 1024
 15 #define HOME_PAGE "index.html"
 16 #define PAGE_404 "wwwroot/404.html"
 17 
 18 static void usage(const char *proc)
 19 {
 20     printf("Usage:%s [port]\n",proc);
 21 }
 22 
 23 static int startup(int port)
 24 {
 25     int sock = socket(AF_INET,SOCK_STREAM,0);
 26     if(sock < 0){
 27         perror("socket");
 28         exit(2);
 29     }
 30 
 31     int opt = 1;
 32     setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof(opt));
 33 
 34     struct sockaddr_in local;
 35     local.sin_family = AF_INET;
 36     local.sin_addr.s_addr = htonl(INADDR_ANY);
 37     local.sin_port = htons(port);
 38 
 39     if(bind(sock,(struct sockaddr*)&local,sizeof(local)) < 0){
 40         perror("bind");
 41         exit(3);
 42     }
 43 
 44     if(listen(sock,5) < 0){
 45         perror("listen");
 46         exit(4);
 47     }
 48 
 49     return sock;
 50 }
 51 
 52 static int getLine(int sock,char line[],int size)
 53 {
 54     //\r,\r\n,\n -> \n
 55     char c = 'a';
 56     int i = 0;
 57     while(c != '\n' && i < size - 1){
 58         ssize_t s = recv(sock,&c,1,0);
 59         if(c == '\r'){
 60             recv(sock,&c,1,MSG_PEEK);
 61             if(c== '\n'){
 62                 recv(sock,&c,1,0);
 63             }else{
 64                 c = '\n';
 65             }
 66         }
 67         line[i++] = c;
 68     }
 69     line[i] = '\0';
 70     return i;
 71 }
 72 
 73 static void clearHeader(int sock)
 74 {
 75     char line[MAX];
 76     do{
 77         getLine(sock,line,sizeof(line));
 78     }while(strcmp("\n",line));
 79 }
 80 
 81 void show_404(int sock)
 82 {
 83     char line[MAX];
 84     struct stat st;
 85     sprintf(line,"HTTP/1.0 404 NOT FOUND\r\n");
 86     send(sock,line,strlen(line),0);
 87     sprintf(line,"Content-Type:text/html:charset=ISO-8859-1\r\n");
 88     send(sock,line,strlen(line),0);
 89     sprintf(line,"\r\n");
 90     send(sock,line,strlen(line),0);
 91     int fd = open(PAGE_404,O_RDONLY);
 92     stat(PAGE_404,&st);
 93     sendfile(sock,fd,NULL,st.st_size);
 94     close(fd);
 95 }
 96 
 97 static void echoErrMsg(int sock,int status_code)
 98 {
 99     switch(status_code){
100         case 301:
101             break;
102         case 302:
103             break;
104         case 307:
105             break;
106         case 400:
107             break;
108         case 403:
109             break;
110         case 404:
111             show_404(sock);
112             break;
113         case 500:
114             break;
115         case 503:
116             break;
117         default:
118             break;
119     }
120 }
121 
122 int exe_cgi(int sock,char *method,char *path,char *query_string)
123 {
124     char line[MAX];
125     int content_length = -1;
126     char method_env[MAX/32];
127     char query_string_env[MAX];
128     char content_length_env[MAX/8];
129 
130     if(strcasecmp(method,"GET") == 0){
131         clearHeader(sock);
132     }else{ //POST
133         do{
134             getLine(sock,line,sizeof(line));
135             if(strncasecmp(line,"Content-Length: ",16) == 0){
136                 content_length = atoi(line + 16);
137             }
138         }while(strcmp(line,"\n"));
139         if(content_length == -1){
140             return 400;
141         }
142     }
143 
144     int input[2];
145     int output[2]; 
146 
147     pipe(input);
148     pipe(output);
149 
150     pid_t id = fork();
151     if(id < 0){
152         return 500;
153     }
154     else if(id == 0){ //child
155         close(input[1]);
156         close(output[0]);
157 
158         dup2(input[0],0);
159         dup2(output[1],1);
160 
161         sprintf(method_env,"METHOD=%s",method);
162         putenv(method_env);
163         if(strcasecmp(method,"GET") == 0){
164             sprintf(query_string_env,"QUERY_STRING=%s",query_string);
165             putenv(query_string_env);
166         }
167         else{
168             sprintf(content_length_env,"CONTENT_LENGTH=%d",content_length);
169             putenv(content_length_env);
170         }
171         execl(path,path,NULL);
172         exit(1);
173     }
174     else{
175         close(input[0]);
176         close(output[1]);
177 
178         sprintf(line,"HTTP/1.0 200 OK\r\n");
179         send(sock,line,strlen(line),0);
180         sprintf(line,"Content-Type: text/html:charset=ISO-8859-1\r\n");
181         send(sock,line,strlen(line),0);
182         sprintf(line,"\r\n");
183         send(sock,line,strlen(line),0);
184 
185         int i = 0;
186         char c;
187         if(strcasecmp(method,"POST") == 0){
188             for(; i < content_length; i++){
189                 recv(sock,&c,1,0);
190                 write(input[1],&c,1);
191             }
192         }
193 
194         while(read(output[0],&c,1) > 0){
195             send(sock,&c,1,0);
196         }
197 
198         waitpid(id,NULL,0);
199         close(input[1]);
200         close(output[0]);
201     }
202     return 200;
203 }
204 
205 int echo_www(int sock,char *path,int size)
206 {
207     char line[MAX];
208     clearHeader(sock);
209 
210     int fd = open(path,O_RDONLY);
211     if(fd < 0){
212         return 404;
213     }
214 
215     sprintf(line,"HTTP/1.0 200 OK\r\n");
216     send(sock,line,strlen(line),0);
217     sprintf(line,"Content-Type: text/html;charset=ISO-8859-1\r\n");
218     send(sock,line,strlen(line),0);
219     sprintf(line,"\r\n");
220     send(sock,line,strlen(line),0);
221 
222     sendfile(sock,fd,NULL,size);
223 
224     close(fd);
225 
226     return 200;
227 }
228 
229 void *handlerRequest(void *arg)
230 {
231     int sock = (int)arg;
232     int status_code = 200;
233     char line[MAX];
234     char method[MAX/16];
235     char url[MAX];
236     char path[MAX];
237     int cgi = 0;
238     char *query_string = NULL;
239 
240     getLine(sock,line,sizeof(line));
241     printf("%s",line);
242     int i = 0;
243     int j = 0;
244     while(i < sizeof(method)-1 && j < sizeof(line) && !isspace(line[j])){
245         method[i] = line[j];
246         i++,j++;
247     }
248     method[i] = '\0';
249 
250     while(j < sizeof(line) && isspace(line[j])){
251         j++;
252     }
253     //line[] = GET /a/b/c.html HTTP/1.1
254     i = 0;
255     while(i < sizeof(url) - 1 && j < sizeof(line) && !isspace(line[j])){
256         url[i] = line[j];
257         i++,j++;
258     }
259     url[i] = '\0';
260     printf("method: %s, url: %s\n",method,url);
261 
262     if(strcasecmp(method,"GET") == 0){
263     }
264     else if(strcasecmp(method,"POST") == 0){
265         cgi = 1;
266     }
267     else{
268         //method error
269         status_code = 400;
270         clearHeader(sock);
271         goto end;
272     }
273 
274     if(strcasecmp(method,"GET") == 0){
275         query_string = url;
276         while(*query_string){
277             if(*query_string == '?'){
278                 cgi = 1;
279                 *query_string = '\0';
280                 query_string++;
281                 break;
282             }
283             query_string++;
284         }
285     }
286 
287     sprintf(path,"wwwroot%s",url);
288     if(path[strlen(path)-1] == '/'){
289         strcat(path,HOME_PAGE);
290     }
291 
292     struct stat st;
293     if(stat(path,&st) < 0){
294         status_code = 404;
295         clearHeader(sock);
296         goto end;
297     }
298     else{
299         // [wwwroot]  /a/b/c  \0x=100&y=200
300         if(S_ISDIR(st.st_mode)){
301             strcat(path,"/");
302             strcat(path,HOME_PAGE);
303         }
304         else if((st.st_mode & S_IXUSR) || (st.st_mode & S_IXGRP) || (st.st_mode & S_IXOTH)){
305             cgi = 1;
306         }
307         else{
308             //Do Nothing
309         }
310 
311         //method, path, cgi, get->query_string
312         if(cgi){
313             status_code = exe_cgi(sock,method,path,query_string);
314         }
315         else{
316             status_code = echo_www(sock,path,st.st_size);
317         }
318     }
319 
320 end:
321     if(status_code != 200){
322         echoErrMsg(sock,status_code);
323     }
324     close(sock);
325 }
326 
327 
328 
329 int main(int argc,char *argv[])
330 {
331     if(argc != 2){
332         usage(argv[0]);
333         return 1;
334     }
335 
336     int listen_sock = startup(atoi(argv[1]));
337     for(;;){
338         struct sockaddr_in client;
339         socklen_t len = sizeof(client);
340         int sock = accept(listen_sock,(struct sockaddr*)&client,&len);
341         if(sock < 0){
342             perror("accept");
343             continue;
344         }
345 
346         pthread_t tid;
347         pthread_create(&tid,NULL,handlerRequest,(void *)sock);
348         pthread_detach(tid);
349     }
350 }   

Makefile檔案

  1 WORK_DIR=$(shell pwd)
  2 cc=gcc
  3 bin=httpd
  4 src=httpd.c
  5 LDFLAGS=-lpthread
  6 
  7 .PHONY:all
  8 all:$(bin) cgi
  9 
 10 $(bin):$(src)
 11     $(cc) -o [email protected] $^ $(LDFLAGS)
 12 
 13 cgi:
 14     cd wwwroot/cgi;make clean;make;cd -
 15     cd sql_connect;make clean;make;cd -
 16 
 17 .PHONY:clean
 18 clean:
 19     rm -f $(bin)
 20     cd wwwroot/cgi;make clean;cd -
 21     cd sql_connect;make clean;cd -
 22     rm -rf output
 23 
 24 .PHONY:output
 25 output:
 26     mkdir -p output/wwwroot/image
 27     mkdir -p output/wwwroot/cgi
 28     mkdir -p output/lib
 29     cp httpd output
 30     cp -rf lib/lib/* output/lib
 31     cp wwwroot/*.html output/wwwroot
 32     cp wwwroot/image/* output/wwwroot/image
 33     cp wwwroot/cgi/math_cgi output/wwwroot/cgi
 34     cp sql_connect/insert_cgi output/wwwroot/cgi
 35     cp sql_connect/select_cgi output/wwwroot/cgi

sql_connect目錄中的檔案 comm.h程式碼

  1 #pragma once
  2 
  3 #include<iostream>
  4 #include<string>
  5 #include<mysql.h>
  6 
  7 MYSQL* connectMysql();
  8 int insertMysql(MYSQL *myfd,const std::string &name,const std::string &sex,const std::string &hobby);
  9 void selectMysql(MYSQL *myfd);
 10 void closeMysql(MYSQL *myfd);

comm.cpp程式碼

  1 #include "comm.h"
  2 
  3 MYSQL* connectMysql()
  4 {
  5     MYSQL *myfd = mysql_init(NULL);
  6     if(mysql_real_connect(myfd,"127.0.0.1","root","","code",3306,NULL,0) == NULL){
  7         std::cerr << "connect error" << std::endl;
  8     }
  9     else{
 10         std::cout << "connect success" << std:: endl;
 11     }
 12 
 13     return myfd;
 14 }
 15 
 16 int insertMysql(MYSQL *myfd,const std::string &name,const std::string &sex,const std::string &hobby)
 17 {
 18     std::string sql="INSERT INTO st_table (name,sex,hobby) VALUES(\"";
 19     sql += name;
 20     sql += "\",\"";
 21 
 22     sql += sex;
 23     sql += "\",\"";
 24     sql += hobby;
 25     sql += "\")";
 26 
 27     std::cout << sql << std::endl;
 28 
 29     return mysql_query(myfd,sql.c_str());
 30 }
 31 
 32 
 33 void selectMysql(MYSQL *myfd)
 34 {
 35     std::string sql = "SELECT * FROM st_table";
 36     mysql_query(myfd,sql.c_str());
 37     MYSQL_RES *result = mysql_store_result(myfd);
 38     int lines = mysql_num_rows(result);
 39     int cols = mysql_num_fields(result);
 40     std::cout << "<table border=\"1\"> " << std::endl;
 41     MYSQL_FIELD *field = mysql_fetch_fields(result);
 42     int i = 0;
 43     std::cout << "<tr>" << std::endl;
 44     for(; i < cols; i++){
 45         std::cout << "<th>" << field[i].name << "</th>";
 46     }
 47     std::cout << "</tr>" << std::endl;
 48 
 49     for(i=0; i < lines; i++){
 50         std::cout << "<tr>" << std::endl;
 51         MYSQL_ROW line = mysql_fetch_row(result);
 52         int j = 0;
 53         for(; j < cols; j++){
 54             std::cout << "<td>" << line[j] << "</td>";
 55         }
 56         std::cout << "</tr>" << std::endl;
 57     }
 58     std::cout << "</table>" << std::endl;
 59     free(result);
 60 }
 61 
 62 void closeMysql(MYSQL *myfd)
 63 {
 64     mysql_close(myfd);
 65 }

insert_cgi.cpp程式碼

  1 #include <stdio.h>
  2 #include <stdlib.h>
  3 #include <string.h>
  4 #include "comm.h"
  5 
  6 int main()
  7 {
  8     char arg[1024];
  9     if( getenv("METHOD") ){
 10         if(strcasecmp(getenv("METHOD"), "GET") == 0){
 11             strcpy(arg, getenv("QUERY_STRING"));
 12         }else{
 13             char c;
 14             int i = 0;
 15             int len = atoi(getenv("CONTENT_LENGTH"));
 16             for(; i < len; i++ ){
 17                 read(0, &c, 1);
 18                 arg[i] = c;
 19             }
 20             arg[i] = 0;
 21         }
 22     }
 23 
 24     strtok(arg, "=&");
 25     std::string name = strtok(NULL, "=&");
 26     strtok(NULL, "=&");
 27     std::string sex = strtok(NULL, "=&");
 28     strtok(NULL, "=&");
 29     std::string hobby = strtok(NULL, "=&");
 30 
 31     MYSQL *myfd = connectMysql();
 32     insertMysql(myfd, name,sex, hobby);
 33     closeMysql(myfd);
 34 }

select_cgi.cpp程式碼

  1 #include<stdio.h>
  2 #include<stdlib.h>
  3 #include<string.h>
  4 #include "comm.h"
  5 
  6 int main()
  7 {
  8     char arg[1024];
  9     if(getenv("METHOD")){
 10         if(strcasecmp(getenv("METHOD"),"GET") == 0){
 11             strcpy(arg,getenv("QUERY_STRING"));
 12         }
 13         else{
 14             char c;
 15             int i = 0;
 16             int len = atoi(getenv("CONTENT_LENGTH"));
 17             for(; i < len; i++){
 18                 read(0,&c,1);
 19                 arg[i] = c;
 20             }
 21             arg[i] = 0;
 22         }
 23     }
 24 
 25     MYSQL *myfd = connectMysql();
 26     selectMysql(myfd);
 27     closeMysql(myfd);
 28 }

Makefile檔案

  1 CURR_PATH=$(shell pwd)
  2 LIB=$(CURR_PATH)/../lib
  3 INCLUDE=-I$(LIB)/include
  4 MYSQL_LIB=-L$(LIB)/lib -lmysqlclient
  5 cc=g++
  6 
  7 
  8 .PHONY:all
  9 all:insert_cgi select_cgi
 10 
 11 insert_cgi:insert_cgi.cpp comm.cpp
 12     g++ -o [email protected] $^ $(INCLUDE) $(MYSQL_LIB)
 13 select_cgi:select_cgi.cpp comm.cpp
 14     g++ -o [email protected] $^ $(INCLUDE) $(MYSQL_LIB)
 15 
 16 .PHONY:clean
 17 clean: 
 18     rm -f insert_cgi select_cgi

wwwroot目錄中的檔案 404.html

  1 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml    1-transitional.dtd">
  2 
  3 <html xmlns="http://www.w3.org/1999/xhtml">
  4 
  5 <head>
  6 
  7 <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
  8 
  9 <title>404-Sorry!The Page Is Not Exist</title>
 10 
 11 <style type="text/css">
 12 
 13 .head404{ width:580px; height:234px; margin:50px auto 0 auto; background:url(https://www.baidu.com/Pu    blic/images/head404.png) no-repeat; }
 14 
 15 .txtbg404{ width:499px; height:169px; margin:10px auto 0 auto; background:url(https://www.baidu.com/P    ublic/images/txtbg404.png) no-repeat;}
 16 
 17 .txtbg404 .txtbox{ width:390px; position:relative; top:30px; left:60px;color:#eee; font-size:13px;}
 18 
 19 .txtbg404 .txtbox p {margin:5px 0; line-height:18px;}
 20 
 21 .txtbg404 .txtbox .paddingbox { padding-top:15px;}
 22 
 23 .txtbg404 .txtbox p a { color:#eee; text-decoration:none;}
 24 
 25 .txtbg404 .txtbox p a:hover { color:#FC9D1D; text-decoration:underline;}
 26 
 27 </style>
 28 
 29 </head>
 30 
 31 
 32 
 33 <body bgcolor="#494949">
 34 
 35     <div class="head404"></div>
 36 
 37     <div class="txtbg404">
 38 
 39   <div class="txtbox">
 40 
 41       <p>Sorry,The Page Is Not Exist!</p>
 42 
 43       <p class="paddingbox">Please click on the link below to continue browsing the web page.
 44       </p>
 45 
 46       <p> <a style="cursor:pointer" onclick="history.back()">Previous Page</a></p>
 47 
 48       <p> <a href="https://www.baidu.com">back home</a></p>
 49 
 50     </div>
 51 
 52   </div>
 53 
 54 </body>
 55 
 56 </html>

index.html

  1 CTYPE html>
  2 <html>
  3 <head lang="en">
  4 <meta charset="UTF-8">
  5 <title>background-position魚遊動程式碼 - 原始碼之家</title>
  6 <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
  7 <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale    =1.0, minimum-scale=1.0">
  8 <style>
  9     body{
 10         background-color: lightblue;
 11         overflow:hidden;
 12     }
 13     .fishbox{
 14         width: 200px;
 15         height: 200px;
 16         /*background-color: rgba(0,0,0,0.4);*/
 17         position: absolute;
 18         left:0;
 19         top:0;
 20         animation: run 20s linear infinite;
 21         animation-direction: normal;
 22     }
 23     .fish{
 24         width: 174px;
 25         height: 126px;
 26         position: absolute;
 27         left:35%;
 28         top:0;
 29         background:url(image/fish8.png) no-repeat left top;
 30         /*transition:all 0.8s steps(8) ;*/
 31         animation:active1 0.8s steps(8) infinite;
 32 
 33     }
 34 
 35     .sharkbox{
 36           width: 509px;
 37           height: 270px;
 38           animation: run2 20s linear infinite;
 39     }
 40     .shark{
 41         width: 509px;
 42         height: 270px;
 43         background:url(image/shark1.png) no-repeat;
 44         animation: active2 1s steps(8) infinite;
 45     }
 46 
 47 
 48 
 49 
 50     @keyframes active1 {
 51         0%{
 52 
 53         }
 54         100%{
 55             background-position: left -1008px;
 56         }
 57     }
 58 
 59     @keyframes active2 {
 60         0%{
 61 
 62         }
 63         100%{
 64             background-position: left -2160px;
 65         }
 66     }
 67 
 68     @keyframes run {
 69         0%{
 70 
 71         }
 72 
 73         15%{
 74             transform:translate(600px,0px) rotate(45deg) ;
 75         }
 76 
 77         50%{
 78             transform:translate(600px,350px) rotate(135deg) ;
 79         }
 80 
 81         75%{
 82             transform:translate(50px,300px) rotate(235deg);
 83         }
 84 
 85 
 86         100%{
 87             transform:translate(0px,0px) rotate(360deg) ;
 88         }
 89     }
 90 
 91    @keyframes run2{
 92         0%{
 93             transform:translateX(-600px);
 94         }
 95 
 96         100%{
 97             transform:translateX(2000px);
 98         }
 99    }
100 </style>
101 </head>
102 <body>
103 
104 <div class="fishbox">
105     <div class="fish"></div>
106 </div>
107 <div class="sharkbox">
108      <div class="shark"></div>
109 </div>
110 
111 <div style="text-align:center;">
112 </div>
113 
114 <img border="0" src="/image/cat.jpeg" alt="Pulpit rock" width="304" height="228">
115 
116 <form action="/cgi/insert_cgi" method="GET">
117 name:
118 <input type="text" name="name" value="">
119 <br>
120 sex:
121 <input type="text" name="sex" value="man">
122 <br>
123 hobby:
124 <input type="text" name="hobby" value="">
125 <br>
126 <input type="submit" value="Submit">
127 </form>
128 <a href="http://192.168.43.243:9999/cgi/select_cgi">select</a>
129 
130 <!--<form action="/cgi/math_cgi" method="GET">
131 x:
132 <input type="text" name="x" value="100">
133 <br>
134 y:
135 <input type="text" name="y" value="200">
136 <br><br>
137 <input type="submit" value="Submit">
138 </form> -->
139 
140 </body>
141 </html>
142 

image資料夾中存放的是圖片 wwwroot目錄裡面的cgi目錄 math_cgi.c程式碼

  1 #include<stdio.h>
  2 #include<string.h>
  3 #include<stdlib.h>
  4 
  5 void math_op(char *buf)
  6 {
  7     int x,y;
  8     sscanf(buf,"x=%d&y=%d",&x,&y);
  9     printf("<html>\n");
 10 
 11     printf("<h1>%d + %d = %d</h1>", x, y, x + y);
 12     printf("<h1>%d - %d = %d</h1>", x, y, x - y);
 13     printf("<h1>%d * %d = %d</h1>", x, y, x * y);
 14     if(y == 0){
 15         printf("<h1>%d / %d = error</h1>", x, y);
 16         printf("<h1>%d % %d = error</h1>", x, y);
 17     }else{
 18         printf("<h1>%d / %d = %d</h1>", x, y, x / y);
 19         printf("<h1>%d % %d = %d</h1>", x, y, x % y);
 20     }
 21     printf("</html>\n");
 22 }
 23 
 24 int main()
 25 {
 26     char buf[1024];
 27     if(getenv("METHOD")){
 28         strcpy(buf, getenv("QUERY_STRING"));
 29     }else{
 30             int len = atoi(getenv("CONTENT_LENGTH"));
 31             int i = 0;
 32             for(; i < len; i++){
 33                 read(0, buf+i, 1);
 34             }
 35             buf[i] = '\0';
 36         }
 37 
 38         printf("arg: %s\n", buf);
 39         math_op(buf);
 40 }

test_cgi.c程式碼

#include <stdio.h>

int main()
{
	printf("<html> <hl>hello cgi</hl> </html>\r\n");
}

Makefile檔案

  1 .PHONY:all
  2 all:math_cgi test_cgi
  3 
  4 math_cgi:math_cgi.c
  5     gcc -o [email protected] $^
  6 test_cgi:test_cgi.c
  7     gcc -o [email protected] $^
  8 
  9 .PHONY:clean
 10 clean:
 11     rm -f math_cgi test_cgi