上一小节已经实现了对图片的传输,接下来就是判断文件是否为js,css,png等格式。我们增加一个函数用于判断格式

  1. int WebServer::get_filetype(char *type,char *path)//用于判断该url指向文件的后缀
  2. {
  3. if(strstr(path,".html"))
  4. strcpy(type,"text/html");
  5. else if(strstr(path,".gif"))
  6. strcpy(type,"image/gif");
  7. else if(strstr(path,".jpg"))
  8. strcpy(type,"image/jpeg");
  9. else if(strstr(path,".png"))
  10. strcpy(type,"image/png");
  11. else if(strstr(path,".ico"))
  12. strcpy(type,"image/x-icon");
  13. else if(strstr(path,".js"))
  14. strcpy(type,"text/javascript");
  15. else if(strstr(path,".json"))
  16. strcpy(type,"application/json");
  17. else if(strstr(path,".css"))
  18. strcpy(type,"text/css");
  19. else
  20. strcpy(type,"text/plain");
  21. return ;
  22. }

  然后修改一下主页index.html的文件

  1. <html>
  2. <head>
  3. <title>Test</title>
  4. <meta http-equiv="Content-Type" content="text/html ; charset=utf-8">
  5. <link rel="stylesheet" href="style.css" type="text/css"/>
  6. <script language="javascript" src="javascript.js"></script>
  7. </head>
  8.  
  9. <body>
  10. <div class="ceshi">图片</div><img src="ab.jpg"></img>
  11. <input name="button" type="button" value="Click!" onclick=hi();></input>
  12. </body>
  13. </html>

  两个外部文件如下

  1. [myuser@bogon www]$ cat style.css
  2. .ceshi {font-size:20px; color:#ff0000;}
  3. [myuser@bogon www]$ cat javascript.js
  4. function hi()
  5. {
  6. alert("js 调用,你单机了按钮");
  7. }
  8. [myuser@bogon www]$

  下面这个是运行的结果图

  用chrome浏览器的F12调试工具获取到的状态,可以看到,该网页可以获取到index.html,然后浏览器会根据这个页面再发送index.html文件所需要的外部文件的请求,从上面可以看出请求了style.css,javascript.js和ab.jpg图片。然后显示网页,我单击了那个button也是可以调用js脚本的。

  接下来就是判断一个提交是get还是post,网页index.html的源代码

  1. <body>
  2. <div class="ceshi">图片</div><img src="ab.jpg"></img>
  3. <input name="button" type="button" value="Click!" onclick=hi();></input>
  4.  
  5. <hr>
  6. <br>使用post方式<br>
  7. <form method="post" name="frm1">
  8. <label>用户名:</label>
  9. <input type="text" name="username" />
  10. <br>
  11. <label>密码:</label>
  12. <input type="password" name="password" />
  13. <br>
  14. <input type="submit" name="commit" value="登陆"/>
  15. <br>
  16. </form>
  17. <hr>
  18. <br>使用get方式<br>
  19. <form method="get" name="frm1" action="index.html">
  20. <label>用户名:</label>
  21. <input type="text" name="username" />
  22. <br>
  23. <label>密码:</label>
  24. <input type="password" name="password" />
  25. <br>
  26. <input type="submit" name="commit" value="登陆"/>
  27. <br>
  28. </form>
  29. </body>

  修改后的ServerRequest函数

  1. int WebServer::ServerRequest(int cli_fd)
  2. {
  3. char buf[];
  4. int size=;
  5. int i,j;
  6. char method[];//用于保存请求方式
  7. char url[];
  8. char path[];
  9. char args[];
  10. struct stat st;
  11. int cgi;//cgi 为0 表示get普通方法 1表示get带参方法 2表示post方法
  12. pid_t pid;
  13. memset(buf,,sizeof(buf));
  14. cgi=;
  15. //获取第一行请求信息 一般格式为: GET / HTTP/1.1
  16. // POST / HTTP/1.1
  17. size=get_line(cli_fd,buf,sizeof(buf));
  18. //cout<<"\t\t"<<buf<<endl;
  19. i=,j=;
  20. //截取第一个单词
  21. while(!isspace(buf[j]) && (i<sizeof(method)-))
  22. {
  23. method[i]=buf[j];
  24. i++;j++;
  25. }
  26. method[i]='\0';
  27. //取第一个与第二个单词之间的空格
  28. while(isspace(buf[j]) && (j<sizeof(buf)))
  29. j++;
  30.  
  31. if(strcasecmp(method,"GET") && strcasecmp(method,"POST"))
  32. {
  33. Page_501(cli_fd);
  34. return -;
  35. }
  36.  
  37. if(strcasecmp(method,"GET")==)
  38. {
  39. cout<<"此次请求的方式是GET方法"<<endl;
  40. cgi=;
  41. }
  42. else if(strcasecmp(method,"POST")==)
  43. {
  44. cout<<"此次请求的方式是POST方法"<<endl;
  45. cgi=;
  46. }
  47.  
  48. //截取第二个单词
  49. i=;
  50. int flag=;
  51. while(!isspace(buf[j]) && (i<sizeof(url)-) && (j<sizeof(buf)))
  52. {
  53. if(buf[j]=='?')
  54. {
  55. flag=;
  56. j++;
  57. i=;
  58. url[i]='\0';
  59. cgi=(cgi==?:);
  60. continue;
  61. }
  62. if(flag==)
  63. {
  64. url[i]=buf[j];
  65. i++;j++;
  66. }
  67. else if(flag==)
  68. {
  69. args[i]=buf[j];
  70. i++;j++;
  71. }
  72. }
  73. if(flag==)
  74. url[i]='\0';
  75. else
  76. args[i]='\0';
  77.  
  78. sprintf(path,"www%s",url);//这个是web服务器的主目录,这个以后可以处理成读取配置文件,这里就先写固定的www目录
  79. if(path[strlen(path)-]=='/')
  80. strcat(path,"index.html");//同上
  81.  
  82. //cout<<"============>此次请求的地址为:"<<path<<":"<<args<<endl;
  83.  
  84. //根据文件名,获取该文件的文件信息。如果为-1,表示获取该文件失败
  85. if(stat(path,&st)==-)
  86. {
  87. while((size>) && strcmp("\n",buf))//去除掉多余的请求头信息
  88. size=get_line(cli_fd,buf,sizeof(buf));
  89. Page_404(cli_fd);
  90. }
  91. else
  92. {
  93. if(S_ISDIR(st.st_mode))//判断url地址,如果是个目录,那么就访问该目录的index.html
  94. {
  95. strcat(path,"/index.html");
  96. //cout<<"此次请求的地址为:"<<path<<endl;
  97. }
  98. if(!S_ISDIR(st.st_mode)&&((st.st_mode & S_IXUSR) || (st.st_mode & S_IXGRP) || (st.st_mode & S_IXOTH)))//判断该url地址所对应的文件是否是可执行,并且是否有权限
  99. {
  100. cgi=;//是一个cgi程序
  101. }
  102. if(cgi==)//如果cgi为0,那么就表示该url所对应的文件不是cgi程序,而是一个简单的静态页面
  103. {
  104. pid = fork();
  105. if(pid==)
  106. {
  107. ServerCatHttpPage(cli_fd,path,st.st_size);
  108. }
  109. }
  110. else if(cgi==)//get方法带参数
  111. {
  112. pid=fork();
  113. if(pid==)
  114. {
  115. while((size>) && strcmp("\n",buf))//去除掉多余的请求头信息
  116. size=get_line(cli_fd,buf,sizeof(buf));
  117. ServerGetFunction(cli_fd,path,args);
  118. }
  119. }
  120. else if(cgi==)//post方法
  121. {
  122. pid=fork();
  123. if(pid==)
  124. {
  125. int content_length=;
  126. while((size>) && strcmp("\n",buf))//去除掉多余的请求头信息
  127. {
  128. size=get_line(cli_fd,buf,sizeof(buf));
  129. buf[]='\0';
  130. if(strcasecmp(buf,"Content-Length:")==)
  131. {
  132. content_length=atoi(&(buf[]));
  133. }
  134. }
  135. if(content_length==)
  136. {
  137. Page_400(cli_fd);
  138. return ;
  139. }
  140. char c;
  141. j=;
  142. for(int i=;i<content_length;i++)
  143. {
  144. recv(cli_fd,&c,,);
  145. args[j]=c;
  146. j++;
  147. }
  148. args[j]=;
  149. ServerPostFunction(cli_fd,path,args);
  150. }
  151. }
  152. }
  153. close(cli_fd);
  154. return ;
  155. }

  增加的两个处理cgi程序的函数(下小节实现)

  1. int WebServer::ServerGetFunction(int cli_fd,char *path,char *args)
  2. {
  3. cout<<"cli_fd:"<<cli_fd<<" path:"<<path<<" args:"<<args<<endl;
  4. Page_200(cli_fd);
  5. return ;
  6. }
  7. int WebServer::ServerPostFunction(int cli_fd,char *path,char *args)
  8. {
  9. cout<<"cli_fd:"<<cli_fd<<" path:"<<path<<" args:"<<args<<endl;
  10. Page_200(cli_fd);
  11. return ;
  12. }

  下面这个是运行的结果

  从上图可以看出通过GET方法和POST方法都可以正常的获取到从表单那里传过去的参数。我们知道中文在url地址中的显示是显示成16进制的。这个是URL编码。接下来要实现对这个URL编码进行转换,这里使用网上别人提供的代码。

  1. #include <ctype.h>
  2. #include <string>
  3. #include <string.h>
  4. #include <stdio.h>
  5. #include <iostream>
  6. #include <stdlib.h>
  7. using namespace std;
  8. static int php_htoi(char *s)
  9. {
  10. int value;
  11. int c;
  12.  
  13. c = ((unsigned char *)s)[];
  14. if (isupper(c))
  15. c = tolower(c);
  16. value = (c >= '' && c <= '' ? c - '' : c - 'a' + ) * ;
  17.  
  18. c = ((unsigned char *)s)[];
  19. if (isupper(c))
  20. c = tolower(c);
  21. value += c >= '' && c <= '' ? c - '' : c - 'a' + ;
  22.  
  23. return (value);
  24. }
  25. /*
  26. *URL解码,提取自PHP 5.2.17
  27. *用法:string urldecode(string str_source)
  28. *时间:2012-8-14 By Dewei
  29. * */
  30. string urldecode(string &str_source)
  31. {
  32. char const *in_str = str_source.c_str();
  33. int in_str_len = strlen(in_str);
  34. int out_str_len = ;
  35. string out_str;
  36. char *str;
  37.  
  38. str = strdup(in_str);
  39. char *dest = str;
  40. char *data = str;
  41.  
  42. while (in_str_len--) {
  43. if (*data == '+') {
  44. *dest = ' ';
  45. }
  46. else if (*data == '%' && in_str_len >= && isxdigit((int) *(data + ))
  47. && isxdigit((int) *(data + ))) {
  48. *dest = (char) php_htoi(data + );
  49. data += ;
  50. in_str_len -= ;
  51. } else {
  52. *dest = *data;
  53. }
  54. data++;
  55. dest++;
  56. }
  57. *dest = '\0';
  58. out_str_len = dest - str;
  59. out_str = str;
  60. free(str);
  61. return out_str;
  62. }
  63.  
  64. int main()
  65. {
  66. string str="username=%E7%99%BB%E5%BD%95";
  67. string out=urldecode(str);
  68. cout<<out<<endl;
  69. return ;
  70. }

  我们通过在传参的时候调用urldecode进行解码就可以实现中文显示了。

  这一节就到这里,下一小节将实现对cgi的支持。

  参考资料: http://blog.csdn.net/xiaojianpitt/article/details/4389247

      : http://dewei.iteye.com/blog/1630969 (关于URL编码解码代码)

  本文地址: http://www.cnblogs.com/wunaozai/p/3945218.html

Socket网络编程--简单Web服务器(4)的更多相关文章

  1. Socket网络编程--简单Web服务器(6)

    本来是想实现ssl连接的,但是弄了好久都不成功,就索性不做了,等以后有能力再做了.所以这一小节就是本次的最后一节了.就简单的说几个注意点. 1.加个配置文件 使用单例模式,使用一个类,该类保存一些信息 ...

  2. Socket网络编程--简单Web服务器(1)

    这一次的Socket系列准备讲Web服务器.就是编写一个简单的Web服务器,具体怎么做呢?我也不是很清楚流程,所以我找来了一个开源的小的Web服务器--tinyhttpd.这个服务器才500多行的代码 ...

  3. Socket网络编程--简单Web服务器(2)

    上一小节通过阅读开源的Web服务器--tinyhttpd.大概知道了一次交互的请求信息和应答信息的具体过程.接下来我就自己简单的实现一个Web服务器. 下面这个程序只是实现一个简单的框架出来.这次先实 ...

  4. Socket网络编程--简单Web服务器(3)

    上一小节已经实现了浏览器发送请求,然后服务器给出应答信息,然后浏览器显示出服务器发送过来的网页.一切看起来都是那么的美好.这一小节就准备实现可以根据地址栏url的不同来返回指定的网页.目前还不考虑带参 ...

  5. Socket网络编程--简单Web服务器(5)

    这一小节我们将实现服务器对get和post的请求进行对cgi程序的调用.对于web服务器以前的章节已经实现了对get和post请求的调用接口,接下来给出对应接口的实现. int WebServer:: ...

  6. C++ socket 网络编程 简单聊天室

    操作系统里的进程通讯方式有6种:(有名/匿名)管道.信号.消息队列.信号量.内存(最快).套接字(最常用),这里我们来介绍用socket来实现进程通讯. 1.简单实现一个单向发送与接收 这是套接字的工 ...

  7. C#中使用Socket实现简单Web服务器

    上一篇博客中介绍了怎样使用socket访问web服务器.关键有两个: 熟悉Socket编程: 熟悉HTTP协议. 上一篇主要是通过socket来模拟浏览器向(任何)Web服务器发送(HTTP)请求,重 ...

  8. Java Web 基础(一) 基于TCP的Socket网络编程

    一.Socket简单介绍 Socket通信作为Java网络通讯的基础内容,集中了异常.I/O流模式等众多知识点.学习Socket通信,既能够了解真正的网络通讯原理,也能够增强对I/O流模式的理解. 1 ...

  9. python之Socket网络编程

    什么是网络? 网络是由节点和连线构成,表示诸多对象及其相互联系.在数学上,网络是一种图,一般认为专指加权图.网络除了数学定义外,还有具体的物理含义,即网络是从某种相同类型的实际问题中抽象出来的模型.在 ...

随机推荐

  1. C6000 CSL 函数说明

    转自:http://bbs.21ic.com/icview-741800-1-1.html 先来看一个例子 代码1 CSL_FINST(osdRegs->VIDWINMD, OSD_VIDWIN ...

  2. 13,EasyNetQ-错误条件

    在本节中,我们将看看任何消息系统中可能出现的各种错误情况,并查看EasyNetQ如何处理它们. 1,我的订阅服务死亡 你已经写了一个订阅了我的NewCustomerMessage的windows服务. ...

  3. OSINT系列:网站信任评估WOT

     OSINT系列:网站信任评估WOT Web of Trust(WOT)是芬兰的一家网站信任评估服务公司.它通过收集用户对网站的评价,来评估网站的可信任度.在该公司网站www.mywot.com,用户 ...

  4. reactNative环境搭建+打包+部分报错总结

    个人搭建记录+个人收集: 多些真诚,少些坑. 排版书写过程可能不够详细,还望见谅. 详细见:http://files.cnblogs.com/files/chunlei36/reactNative%E ...

  5. npm和yarn

    在2016年10月11日facebook公开了新的javascript包管理工具yarn,用来替代目前被广泛使用的npm(nodejs 自带的包管理工具)

  6. BZOJ.3425.[POI2013]Polarization(DP 多重背包 二进制优化)

    BZOJ 洛谷 最小可到达点对数自然是把一条路径上的边不断反向,也就是黑白染色后都由黑点指向白点.这样答案就是\(n-1\). 最大可到达点对数,容易想到找一个点\(a\),然后将其子树分为两部分\( ...

  7. BZOJ.3262.陌上花开([模板]CDQ分治 三维偏序)

    题目链接 BZOJ3262 洛谷P3810 /* 5904kb 872ms 对于相邻x,y,z相同的元素要进行去重,并记录次数算入贡献(它们之间产生的答案是一样的,但不去重会..) */ #inclu ...

  8. Python3内置函数——reversed() = 翻转我的世界

    认识reversed单词 reversed 英[rɪ'vɜ:st] 美[rɪ'vɜst] adj. 颠倒的:相反的:(判决等)撤销的 v. 颠倒(reverse的过去式和过去分词):翻转 help(r ...

  9. 微信企业号开发之weixin://preInjectJSBridge/fail

    最近几天遇到个奇怪的问题,目前只有在Andriod平台上出现:weixin://preInjectJSBridge/fail 不止我一个人遇到这个问题,群里也有好几个问了这个问题.这个问题直接导致我们 ...

  10. Vs2017 控制台 中文输出是乱码的问题解决

    下午直接用vs写的控制台的东西,然后发现控制台输出的中文是乱码,于是就百度了下.同样的是,百度上很多的答案.我就说下我解决的过程.先上图 第一种方案:有可能是控制台的问题.若是控制台的问题,则与VS无 ...