免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 2938 | 回复: 2
打印 上一主题 下一主题

[C] web server code [复制链接]

论坛徽章:
1
2015年迎新春徽章
日期:2015-03-04 09:49:03
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2010-01-02 18:59 |只看该作者 |倒序浏览
  1. #include <stdio.h>
  2. #include <sys/socket.h>
  3. #include <netinet/in.h>
  4. #include <errno.h>
  5. #include <netdb.h>  
  6. #include <sys/types.h>   
  7. #include <stdio.h>   
  8. #include <errno.h>   
  9. #include <sys/ioctl.h>   
  10. #include <net/if.h>   
  11. #include <netinet/ip.h>   
  12. #include <netinet/in.h>   
  13. #include <string.h>   
  14. #include <arpa/inet.h>   
  15. #include <netinet/tcp.h>   
  16. #include <pthread.h>     
  17. #include <signal.h>   
  18. #include <fcntl.h>  
  19. #include <sys/types.h>   
  20. #include <sys/stat.h>   
  21. #include <unistd.h>
  22. #include <glib.h>
  23. #include <gtk/gtk.h>

  24. #define SERVER_PORT 80
  25. #define MAX_BUF 8192

  26. #define GET_COMMON   0
  27. #define GET_CGI   1
  28. #define HEAD   2
  29. #define POST   3
  30. #define BAD_REQUEST -1

  31. int gServerStatus = 0;
  32. int gIsRun = 0;

  33. FILE *pfilelog = NULL;

  34. /* 程序執行流程為基於請求鏈的傳遞,具體流程為通過解析函數,解析本次請求鏈;
  35.   分析本次請求鏈,調用相關模塊執行,生成響應頭信息,以及定位文件信息
  36.   發送響應頭信息以及文件,更新日誌記錄
  37. */
  38. typedef struct HttpRequest
  39. {
  40.         char method[20]; // 請求方法
  41.         char *path; // 請求路徑及資源名,若為CGI則為請求的可執行程序路徑
  42.         char *content; // 請求內容,面向POST和GET CGI請求
  43.         int contentlength; // 請求內容的長度
  44.         int                        contenttype;        /* 迴響的內容類型: */
  45.         int                        rangeflag;     /* 以下用於斷點續傳,分別表示斷點起始點,結束點以及總長度*/
  46.         long                rangestart;
  47.         long                rangeend;
  48.         long                rangetotal;       
  49.         char            prefix[20];
  50.         int  responsecode; //響應碼
  51. }HR;

  52. /*
  53.   解析請求, 順次解析各行
  54. */
  55. FILE* isexistfile(char *filename)
  56. {
  57.         FILE *fp = NULL;
  58.         fp = fopen(filename,"r");
  59.         return fp;
  60. }

  61. int getrequest(char *requestbuf,struct HttpRequest *prequest)
  62. {
  63.         char protocol[20];       
  64.         char path[200];
  65.         int i = 0;
  66.         if(sscanf(requestbuf, "%s %s %s", prequest->method, path, protocol)!=3)
  67.                 return BAD_REQUEST;
  68.         if(strcmp(prequest->method,"GET") == 0)
  69.         {
  70.                 if(strchr(path, '?') == NULL)
  71.                 {
  72.                         // 先判斷是否最後一個字符為/,如果為/則,掛加index.htm
  73.                         if(path[strlen(path)-1] == '/')
  74.                                 strcat(path,"index.htm");
  75.                         //在之前添加./web 這是默認目錄
  76.                         sprintf(prequest->path,"./web%s",path);
  77.                         // 求後綴信息,若沒有,則置為*
  78.                         if(sscanf(path, "%s.%s", path, prequest->prefix)!=2)
  79.                                 strcpy(prequest->prefix,"*");
  80.                        
  81.                         printf("GET path:%s\nprefix:%s\n",prequest->path,prequest->prefix);
  82.                         return GET_COMMON;
  83.                 }
  84.                 else
  85.                 {
  86.                         prequest->content = (char *)malloc(strlen(prequest->path));
  87.                         printf("run ?  \n");
  88.                         sscanf(prequest->path,"%s?%s",prequest->path, prequest->content);
  89.                         printf("run ?  %s|%s \n",prequest->path, prequest->content);
  90.                         return GET_CGI;
  91.                 }       
  92.         }               
  93.         else if(strcmp(prequest->method,"POST") == 0)
  94.         {
  95.                 return POST;
  96.         }
  97.         else if(strcmp(prequest->method,"HEAD") == 0)
  98.         {
  99.                 return HEAD;
  100.         }
  101.         else if(strcmp(prequest->method,"TRACR") == 0)
  102.         {
  103.                 return TRACR;
  104.         }
  105.         return -1;
  106. }
  107. char* getcontenttype(char *type)
  108. {
  109.         // 返回內容type
  110.         char ContentType[][27] ={
  111.                         "jpeg", "image/jpeg",
  112.                         "png", "image/png",
  113.                         "mpg", "video/mpeg",
  114.                         "asf", "video/x-ms-asf",
  115.                         "avi", "video/x-msvideo",
  116.                         "bmp", "image/bmp",
  117.                         "doc", "application/msword",
  118.                         "exe", "application/octet-stream",//14, 15
  119.                         "rar", "application/octet-stream",
  120.                         "zip", "application/zip",
  121.                         "jpg", "image/jpeg",
  122.                         "gif", "image/gif",
  123.                         "txt", "text/plain",
  124.                         "c", "text/plain",
  125.                         "cpp", "text/plain",
  126.                         "cxx", "text/plain",
  127.                         "h", "text/plain",
  128.                         "ico", "image/x-icon",
  129.                         "css", "text/css",
  130.                         "htm", "text/html",
  131.                         "html", "text/html"
  132.                         "*", "application/octet-stream"
  133.         };       
  134.         int nType = sizeof(ContentType)/27;
  135.         int i;
  136.         for(i=0; i<nType; i+=2)
  137.         {
  138.                 if(strcmp(ContentType[i], type) == 0)
  139.                         return ContentType[i+1];
  140.         }
  141.     return "application/octet-stream";
  142. }
  143. char* getcurrenttime()
  144. {
  145. /*        char timebuf[30];
  146.         struct tm *p;
  147.         long ltime;
  148.         time(&ltime);
  149.         p=localtime(&ltime);
  150.         strftime(timebuf,25,"%a %d %b %Y %H:%M:%S",p);
  151.         /*
  152.         time_t now;
  153.         struct tm *timenow;
  154.         char localvalue[30];
  155.         time(&now);
  156.         timenow = localtime(&now);
  157.         sprintf(localvalue,"%s",asctime(&now));
  158. //        localvalue[strlen(localvalue)-1] = '\0';
  159.         printf("localtime :%s\n",localvalue);
  160.         */
  161.         time_t timep;
  162.         char localvalue[30];
  163.         time (&timep);

  164.         sprintf(localvalue,"%s",asctime(gmtime(&timep)));
  165.         printf("localtime :%s",localvalue);
  166.         return localvalue;
  167. }
  168. // 構建響應碼,發送響應碼信息
  169. void responsecode(int s,int code,struct HttpRequest *prequest)
  170. {

  171.         char buffer[2048];
  172.         char contenttype[200];
  173.         char content[1023];
  174.        
  175.         prequest->responsecode = code;
  176.         // 構建響應報文頭
  177.         switch(code)
  178.         {
  179.         case 200:
  180.                 sprintf(buffer,
  181.                         "HTTP/1.1 200 OK\r\n"
  182.                         "Server: LiuServer/1.0\r\n"
  183.                         "Date: %s\r\n"
  184.                         "Content-Type: %s\r\n"
  185.                         "Accept-Ranges: bytes\r\n"                       
  186.                         "Content-Length: %d\r\n"
  187.                         "Connection: close\r\n"
  188.                         //"\r\n",date,contenttype,prequest->rangetotal);
  189.                         "\r\n",getcurrenttime(),getcontenttype(prequest->prefix),prequest->rangetotal);
  190.                 break;
  191.         case 404:
  192.                 strcpy(content,"<html><head><title>Object Not Found</title></head><body><h1>Object Not Found</h1>File Not Found.</body></html>");
  193.                 sprintf(buffer,
  194.                         "HTTP/1.1 404 Object Not Found\r\n"
  195.                         "Server: LiuServer/1.0\r\n"
  196.                         "Date: %s\r\n"                       
  197.                         "Content-Type: %s\r\n"
  198.                         "Content-Length: %d\r\n"
  199.                         "Connection: close\r\n"
  200.                         "\r\n"
  201.                         "%s", getcurrenttime(),getcontenttype(prequest->prefix),strlen(content), content);
  202.                 break;
  203.         case 505:
  204.                 break;
  205.         default:
  206.                 break;
  207.         }
  208.         sendsegment(s,buffer,strlen(buffer));
  209. }
  210. void processgetcommon(int s,struct HttpRequest *prequest)
  211. {
  212.         // 先判斷文件是否存在
  213.         FILE *fp = isexistfile(prequest->path);
  214.         printf("%s\n",prequest->path);
  215.         struct stat finfo;
  216.         if(fp == NULL)
  217.         {
  218.                 responsecode(s,404,prequest);
  219.         }
  220.         else
  221.         {               
  222.                 if(prequest->rangeflag == 0)
  223.                 {                       
  224.                         stat(prequest->path,&finfo);
  225.                         prequest->rangetotal = finfo.st_size;
  226.                 }
  227.                 responsecode(s,200,prequest);
  228.                 transferfile(s,fp,prequest->rangeflag,prequest->rangestart,prequest->rangetotal);
  229.                 fclose(fp);
  230.         }
  231. }
  232. void processgetcgi(int s,struct HttpRequest *prequest)
  233. {
  234.         system("hello");
  235.        
  236. }
  237. void processpost(int s,struct HttpRequest *prequest)
  238. {

  239. }
  240. void processhead(int s,struct HttpRequest *prequest)
  241. {

  242. }
  243. // 參數的含義為
  244. int transferfile(int s,FILE *fp,int type,int rangstart,int totallength)
  245. {
  246.         if(type == 1)
  247.         {
  248.                 // 為1 則表示當前從指定的位置傳送文件
  249.                 fseek(fp,rangstart,0);               
  250.         }
  251.         int sendnum = 0;
  252.         int segment = 1024;
  253.         while(!feof(fp)&&sendnum < totallength)
  254.         {
  255.                 char buf[segment];
  256.                 memset(buf,0,1024);
  257.                 int i = 0;
  258.                 while(!feof(fp) && i < segment && sendnum+i < totallength)
  259.                 {               
  260.                         buf[i++] = fgetc(fp);                                       
  261.                 }
  262.                 if(sendsegment(s,buf,i) == 0)
  263.                         return 0;
  264.                 sendnum += i;
  265.         }
  266.         return 1;
  267. }
  268. int sendsegment(int s, char *buffer,int length)
  269. {
  270.         if(length <= 0)
  271.                 return 0;
  272.         printf("%s\n",buffer);
  273.         int result = send(s,buffer,length,0);
  274.         if(result < 0)
  275.                 return 0;
  276.         return 1;
  277. }

  278. // 日誌文件採用XML格式存儲
  279. FILE* openlogfile(FILE *fp)
  280. {
  281.         char filename[200];
  282.         sprintf(filename,"./log/%s.xml",getcurrenttime());
  283.         fp = fopen(filename,"ab+");
  284.         if(fp == NULL)
  285.         {
  286.                 printf("can't open this file[%s]\n",filename);
  287.                 return NULL;
  288.         }
  289.         fputs("<?xml version=\"1.0\" encoding=\"GB2312\"?>",fp);
  290.         fputs("<Log>",fp);
  291.         fflush(fp);
  292.         return fp;
  293. }
  294. void closelogfile(FILE *fp)
  295. {
  296.         if(fp == NULL)
  297.                 return;
  298.         fputs("</Log>",fp);
  299.         fclose(fp);
  300. }

  301. void insertlognode(FILE *fp,struct HttpRequest *prequest)
  302. {
  303.         if(fp == NULL)
  304.                 return;
  305.         fputs("<record>",fp);
  306.         fputs("<method>",fp);
  307.         fputs(prequest->method,fp);
  308.         fputs("</method>",fp);
  309.         fputs("<path>",fp);
  310.         fputs(prequest->path,fp);
  311.         fputs("</path>",fp);
  312.         char reponsecode[100];
  313.         sprintf(reponsecode,"<reponsecode>%d</reponsecode>",prequest->responsecode);
  314.         fputs(reponsecode,fp);
  315.         fputs("</record>",fp);
  316.         fflush(fp);
  317. }
  318. void* processthread(void *para)
  319. {
  320.         int clientsocket;
  321.         char buffer[1024];
  322.         int iDataNum =0;
  323.         int recvnum=0;
  324.         clientsocket = *((int *)para);
  325.         printf("<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<BEGIN [%d]>>>>>>>>>>>>>>>>>>>>>>>\n",clientsocket);
  326.         struct HttpRequest httprequest;
  327.         httprequest.content = NULL;
  328.         httprequest.path = NULL;
  329.         httprequest.path = (char *)malloc(1024);
  330.         httprequest.rangeflag = 0;
  331.         httprequest.rangestart = 0;

  332.         while(1)
  333.         {
  334.                 iDataNum = recv(clientsocket,buffer+recvnum,sizeof(buffer)-recvnum-1,0);
  335.                 if(iDataNum <= 0)
  336.                 {
  337.                         close(clientsocket);
  338.                         pthread_exit(NULL);
  339.                         return 0;
  340.                 }
  341.                 recvnum += iDataNum;
  342.                 buffer[recvnum]='\0';
  343.                 if(strstr(buffer,"\r\n\r\n")!=NULL || strstr(buffer,"\n\n")!=NULL)
  344.                         break;
  345.         }
  346.         printf("request: %s\n",buffer);
  347.        
  348.         //解析請求信息並處理請求信息
  349.         switch(getrequest(buffer,&httprequest))
  350.         {
  351.         case GET_COMMON:
  352.                 processgetcommon(clientsocket,&httprequest);
  353.                 break;
  354.         case GET_CGI:
  355.                 processgetcgi(clientsocket,&httprequest);
  356.                 break;
  357.         case POST:
  358.                 processpost(clientsocket,&httprequest);
  359.                 break;
  360.         case HEAD:
  361.                 processhead(clientsocket,&httprequest);
  362.                 break;
  363.         default:
  364.                 break;
  365.         }                       
  366.         insertlognode(pfilelog,&httprequest);
  367.         if(httprequest.path != NULL)
  368.                 free(httprequest.path);
  369.         if(httprequest.content != NULL)
  370.                 free(httprequest.content);
  371.         close(clientsocket);
  372.         printf("<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<END [%d]>>>>>>>>>>>>>>>>>>>>>>>\n",clientsocket);
  373.         pthread_exit(NULL);       
  374. }
  375. void* server_process(void *p)
  376. {
  377.         int serverSocket;
  378.         struct sockaddr_in server_addr;
  379.         struct sockaddr_in clientAddr;
  380.         int addr_len = sizeof(clientAddr);       

  381.         if((serverSocket = socket(AF_INET,SOCK_STREAM,0)) < 0)
  382.         {
  383.                 perror( "error: create server socket!!!");
  384.                 exit(1);
  385.         }

  386.         bzero(&server_addr,sizeof(server_addr));
  387.         server_addr.sin_family =AF_INET;
  388.         server_addr.sin_port = htons(SERVER_PORT);
  389.         server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
  390.         if(bind(serverSocket,(struct sockaddr *)&server_addr,sizeof(server_addr)) < 0)
  391.         {
  392.                 perror("error: bind address !!!!");
  393.                 exit(1);
  394.         }

  395.         if(listen(serverSocket,5)<0)
  396.         {
  397.                 perror("error: listen !!!!");
  398.                 exit(1);
  399.         }
  400.         gIsRun = 1;       
  401.         printf("LiuServer is running.....\n");

  402.         while(gIsRun)
  403.         {               
  404.                 int clientsocket;
  405.                 clientsocket = accept(serverSocket,(struct sockaddr *)&clientAddr,(socklen_t*)&addr_len);
  406.                 if(clientsocket < 0)
  407.                 {
  408.                         perror("error: accept client socket !!!");
  409.                         continue;
  410.                 }
  411.                 if(gServerStatus == 0)
  412.                 {
  413.                         close(clientsocket);
  414.                 }
  415.                 else if(gServerStatus == 1)
  416.                 {
  417.                         pthread_t threadid;
  418.                         int temp;
  419.                         temp = pthread_create(&threadid, NULL, processthread, (void *)&clientsocket);   
  420.                         /*if(threadid !=0)
  421.                         {                  
  422.                                  pthread_join(threadid,NULL);
  423.                         }*/
  424.                 }
  425.         }       
  426.         close(serverSocket);
  427. }

  428. void run_button( GtkWidget *widget,
  429.                gpointer   data )
  430. {
  431.    // g_print ("run was pressed\n");
  432.         if(gIsRun == 0)
  433.         {
  434.                 pthread_t threadid;
  435.                 int temp;
  436.                 temp = pthread_create(&threadid, NULL, server_process, NULL);  
  437.                 gServerStatus = 1;
  438.         }
  439.         else
  440.         {
  441.                 if(gServerStatus == 0)
  442.                         gServerStatus = 1;
  443.                 else
  444.                 {
  445.                         printf("is runnning.....\n ");
  446.                 }
  447.         }
  448.         gtk_label_set_text( (GtkLabel*)data,"Server Status: run....");
  449. }
  450. void pause_button( GtkWidget *widget,
  451.                gpointer   data )
  452. {
  453.         if(gIsRun == 1)
  454.         {
  455.                 if(gServerStatus == 1)
  456.                 {
  457.                         gServerStatus = 0;
  458.                 }
  459.                 else
  460.                 {
  461.                         printf("is pause\n");
  462.                 }
  463.                 gtk_label_set_text( (GtkLabel*)data,"Server Status: pause");       
  464.         }
  465.         else
  466.         {
  467.                 printf("need run....\n");
  468.         }
  469.        
  470. }

  471. gint close_application( GtkWidget *widget,
  472.                         GdkEvent  *event,
  473.                         gpointer   data )
  474. {
  475. /*        if(gIsRun == 1)
  476.         {
  477.                 gIsRun = 0;               
  478.                 while(!gIsRun)
  479.                 {
  480.                         sleep(1);
  481.                         printf("waitting for end................\n");
  482.                 }
  483.         }
  484. */
  485.         closelogfile(pfilelog);
  486.         gtk_main_quit ();
  487.         return FALSE;
  488. }

  489. int main( int   argc,
  490.           char *argv[] )
  491. {
  492.     GtkWidget *window = NULL;
  493.     GtkWidget *box1;
  494.     GtkWidget *box2;
  495.     GtkWidget *button;
  496.         GtkWidget *label;
  497.     GtkWidget *separator;

  498.        
  499.   
  500.     gtk_init (&argc, &argv);   
  501.       
  502.     window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
  503.   
  504.     g_signal_connect (G_OBJECT (window), "delete_event",
  505.                       G_CALLBACK (close_application),
  506.                       NULL);

  507.     gtk_window_set_title (GTK_WINDOW (window), "LiuServer 1.0");
  508.     gtk_container_set_border_width (GTK_CONTAINER (window), 20);

  509.     box1 = gtk_vbox_new (FALSE, 0);
  510.     gtk_container_add (GTK_CONTAINER (window), box1);
  511.     gtk_widget_show (box1);

  512.     box2 = gtk_vbox_new (FALSE, 10);
  513.     gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
  514.     gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
  515.     gtk_widget_show (box2);
  516.        
  517.         label = gtk_label_new ("Server Status: stop");

  518.     button = gtk_button_new_with_label ("Run");
  519.         g_signal_connect (G_OBJECT (button), "clicked",
  520.                       G_CALLBACK (run_button), G_OBJECT(label));

  521.     gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
  522.     gtk_widget_show (button);

  523.    
  524.     button = gtk_button_new_with_label ("Pause");
  525.         g_signal_connect (G_OBJECT (button), "clicked",
  526.                       G_CALLBACK (pause_button), G_OBJECT(label));
  527.     gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
  528.     gtk_widget_show (button);

  529.     button = gtk_button_new_with_label ("Stop");
  530.     gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
  531.         g_signal_connect_swapped (G_OBJECT (button), "clicked",
  532.                               G_CALLBACK (close_application),
  533.                               window);
  534.     gtk_widget_show (button);

  535.     separator = gtk_hseparator_new ();
  536.     gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0);
  537.     gtk_widget_show (separator);

  538.     box2 = gtk_vbox_new (FALSE, 10);
  539.     gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
  540.     gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
  541.     gtk_widget_show (box2);

  542.    
  543.    
  544.     gtk_box_pack_start (GTK_BOX (box2), label, TRUE, TRUE, 0);
  545.     GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
  546.     gtk_widget_grab_default (button);
  547.     gtk_widget_show (label);
  548.     gtk_widget_show (window);
  549.      
  550.     gtk_main ();

  551.     return 0;
  552. }
复制代码



gcc webserver.c -o webserver  -lpthread  `pkg-config --cflags --libs gtk+-2.0`

webserver.c: In function ‘getrequest’:
webserver.c:93: warning: incompatible implicit declaration of built-in function ‘malloc’
webserver.c:110: error: ‘TRACR’ undeclared (first use in this function)
webserver.c:110: error: (Each undeclared identifier is reported only once
webserver.c:110: error: for each function it appears in.)
webserver.c: In function ‘getcurrenttime’:
webserver.c:174: warning: function returns address of local variable
webserver.c: In function ‘processthread’:
webserver.c:342: warning: incompatible implicit declaration of built-in function ‘malloc’
webserver.c:382: warning: incompatible implicit declaration of built-in function ‘free’
webserver.c: In function ‘server_process’:
webserver.c:399: warning: incompatible implicit declaration of built-in function ‘exit’
webserver.c:409: warning: incompatible implicit declaration of built-in function ‘exit’
webserver.c:415: warning: incompatible implicit declaration of built-in function ‘exit’



我是書上代碼 不過他TRACR 怎麼沒undeclared

论坛徽章:
0
2 [报告]
发表于 2010-01-02 20:24 |只看该作者
根据你的POST GET
你是不是也应该定义一个TRACR的宏?

论坛徽章:
0
3 [报告]
发表于 2010-01-02 21:15 |只看该作者
1、TRACR => TRACE
2、#define TRACE 4
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP