Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1242759
  • 博文数量: 105
  • 博客积分: 127
  • 博客等级: 入伍新兵
  • 技术积分: 962
  • 用 户 组: 普通用户
  • 注册时间: 2011-01-29 15:22
文章分类

全部博文(105)

文章存档

2021年(1)

2019年(3)

2018年(1)

2017年(11)

2016年(47)

2015年(32)

2014年(4)

2012年(6)

我的朋友

分类: 嵌入式

2015-08-26 14:50:14

             BOA CGI移植与实例实验
--------------------------------------------------------------------------------------------------------------
-----------------由于长的发不了,分两篇吧,紧接上部分---------------------------------------------------------
--------------------------------------------------------------------------------------------------------------

点击 resu按钮后,出现如下页面,大大的Error 肯定就不对了。那么问题就来了。照着别人的做也不是什么问题也没有,
事非经过不知难。


这时候还是比较理智,get可以,post不行。表明链路等已经正确,应该是配置的问题,或者这位兄台的程序有问题。
想起来了error_log,查看了一下,如下:



没有看懂这些log,但发现了最后一句话 Permission denied 。联想前一实验的权限问题,修改完user   group 就出现
如下界面了。



点击(此处)折叠或打开

  1. get源码
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. int main(void)
  5. {
  6.         char *data;
  7.         char a[10],b[10];
  8.         printf("Content-Type:text/html\n\n");
  9.         printf("\n");
  10.         printf("\n\n\n");
  11.         printf("\n");
  12.         printf("\n");
  13.         data = getenv("QUERY_STRING");
  14.         //http://192.168.7.254/cgi-bin/get?a=2&b=4
  15.         if(sscanf(data,"a=%[^&]&b=%s",a,b)!=2){
  16.            printf("Error parameters should be entered!\n");
  17.         }
  18.         else{
  19.                printf("a + b = %d\n",atoi(a)+atoi(b));
  20.         }
  21.         printf("");
  22.         printf("");
  23.         printf("\n");
  24.         printf(" \n");
  25.         printf("\n");
  26.         return 0;
  27. }

sscanf  是对来自于变量的字符串进行输入操作,与scanf 类似。

QUERY_STRING 变量,在我的这次访问中,其实就上面注释部分的后半部分,a=2&b=3

返回参数数目为2,则表示正确解析。

关于sscanf参考如下:

/>


点击(此处)折叠或打开

  1. post 源码
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. int main(void){
  5.         int len;
  6.         char *lenstr,poststr[20];
  7.         char m[10],n[10];
  8.         printf("Content-Type:text/html\n\n");
  9.         printf("\n");
  10.         printf("\n\n\n");
  11.         printf("\n");
  12.         printf("\n");
  13.         lenstr=getenv("CONTENT_LENGTH");
  14.         if(lenstr == NULL)
  15.                 printf("Error parameters should be entered!\n");
  16.         else{
  17.                 len=atoi(lenstr);
  18.                 //http://192.168.7.254/cgi-bin/post
  19.                 fgets(poststr,len+1,stdin);
  20.                 if(sscanf(poststr,"m=%[^&]&n=%s",m,n)!=2){
  21.                         printf("Error: Parameters are not right!\n");
  22.                 }
  23.                 else{
  24.                        printf("m * n = %d\n",atoi(m)*atoi(n));
  25.                 }
  26.         }
  27.         printf("");
  28.         printf("");
  29.         printf("\n");
  30.         printf("\n");
  31.         printf("\n");
  32.         fflush(stdout);
  33.         return 0;
  34. }

上面的注释是可以看得到的,在网址中是没有类似于get时的变量及值的。其中fgets语句会让人有些疑虑,为什么是stdin 呢?
这是因为在boa stdin 已经重定向到了网页这边,这也是printf能输出html的原因。

CGI环境变量列表

SERVER-NAME:运行CGI序为机器名或IP地址。

SERVER-INTERFACEWWW服务器的类型,如:CERN型或NCSA型。  
SERVER-PROTOCOL
:通信协议,应当是HTTP/1.0  

SERVER-PORTTCP端口,一般说来web端口是80

HTTP-ACCEPTHTTP定义的浏览器能够接受的数据类型。

HTTP-REFERER: 发送表单的文件URL。(并非所有的浏览器都传送这一变量)   
HTTP-USER-AGENT
:发送表单的浏览器的有关信息。

GETWAY-INTERFACECGI程序的版本,在UNIX下为 CGI/1.1  

PATH-TRANSLATED PATH-INFO中包含的实际路径名。  

PATH-INFO:浏览器用GET方式发送数据时的附加路径。  

SCRIPT-NAME CGI程序的路径名。

QUERY-STRING:表单输入的数据,URL中间号后的内容。  

REMOTE-HOST:发送程序的主机名,不能确定该值。   

REMOTE-ADDR:发送程序的机器的IP地址。  

REMOTE-USER:发送程序的人名。

CONTENT-TYPEPOST发送,一般为applioation/xwww-form-urlencoded

CONTENT-LENGTHPOST方法输入的数据的字节数。

 

关于get post 方法查了很多资料,还是没有搞得很清楚。但能过上面的实验是可以看得到的,明显post会安全一些,get直接明文传输了。
简单了解可以参考下面的链接:

http://blog.csdn.net/kaloha3/article/details/8548027


<>,使用CGIC 库及实现文件上传                                                                         

实验前,还是要先对CGIC 库做一个介绍。使用C可以进行CGI编程,需要去遵循CGI规范,然后还能发现很多重复的printf 语句。
人类能统治地球的一个原因就是,善于分析总结,化繁为简,转换到IT软件行业,就是TMD善于封装库。CGIC库就是一个让C
CGI程序变得简单的库。源码地址如下:

现在最新版本是2.0.6

 

实验环境:

PC 机 :windows 7

嵌入式主板:IMX287 , linux.2.6.31
实验源码:
cgic_test.rar

PC机与嵌入式主板在同一局域网。

cgi206 源目录如下,其中capture.c ,cgictest.c 均是demo



arm-linux-gcc  cgitest.c  cgic.c –o cgictest.cgi

arm-linux-gcc  capture.c  cgic.c –o capture.cgi

cgictest.cgi capture.cgi 放在嵌入式主板 cgi-bin 目录下面,然后访问得到如下界面:




文件上传功能在上面的demo中其实已经有了。下面是一个专门的完整的文件上传的cgi测试,采用CGIC库,实现起来比较简单。
主要来源于下面这个链接:

http://blog.csdn.net/lanmanck/article/details/5359366

点击(此处)折叠或打开

  1. cgi源码如下:
  2. #include<stdio.h>
  3. #include<string.h>
  4. #include<unistd.h>
  5. #include<fcntl.h>
  6. #include<sys/stat.h>
  7. #include"cgic.h"
  8. #define BufferLen 1024
  9. int cgiMain(void)
  10. {
  11.     cgiFilePtr file;
  12.     int targetFile;
  13.     mode_t mode;
  14.     char name[128];
  15.     char fileNameOnServer[64];
  16.     char contentType[1024];
  17.     char buffer[BufferLen];
  18.     char *tmpStr=NULL;
  19.     int size;
  20.     int got,t;
  21.     cgiHeaderContentType("text/html");
  22.     //取得html页面中file元素的值,应该是文件在客户机上的路径名
  23.     if (cgiFormFileName("file", name, sizeof(name)) !=cgiFormSuccess)
  24.     {
  25.         fprintf(stderr,"could not retrieve filename/n");
  26.         goto FAIL;
  27.     }
  28.     cgiFormFileSize("file", &size);
  29.     //取得文件类型,不过本例中并未使用
  30.     cgiFormFileContentType("file", contentType, sizeof(contentType));
  31.     //目前文件存在于系统临时文件夹中,通常为/tmp,通过该命令打开临时文件。临时文件的名字与用户文件的名字不同,所以不能
  32.     //通过路径/tmp/userfilename的方式获得文件
  33.     if (cgiFormFileOpen("file", &file) != cgiFormSuccess)
  34.     {
  35.         fprintf(stderr,"could not open the file/n");
  36.         goto FAIL;
  37.     }
  38.     t=-1;
  39.     //从路径名解析出用户文件名
  40.     while(1)
  41.     {
  42.         tmpStr=strstr(name+t+1,"//");
  43.         if(NULL==tmpStr)
  44.             tmpStr=strstr(name+t+1,"/");//if "//" is not path separator, try "/"
  45.         if(NULL!=tmpStr)
  46.             t=(int)(tmpStr-name);
  47.         else
  48.             break;
  49.     }
  50.     strcpy(fileNameOnServer,name+t+1);
  51.     mode=S_IRWXU|S_IRGRP|S_IROTH;
  52.     //在当前目录下建立新的文件,第一个参数实际上是路径名,此处的含义是在cgi程序所在的目录(当前目录))建立新文件
  53.     targetFile=open(fileNameOnServer,O_RDWR|O_CREAT|O_TRUNC|O_APPEND,mode);
  54.     if(targetFile<0)
  55.     {
  56.         fprintf(stderr,"could not create the new file,%s/n",fileNameOnServer);
  57.         goto FAIL;
  58.     }
  59.     //从系统临时文件中读出文件内容,并放到刚创建的目标文件中
  60.     while (cgiFormFileRead(file, buffer, BufferLen, &got) ==cgiFormSuccess)
  61.     {
  62.         if(got>0)
  63.         write(targetFile,buffer,got);
  64.     }
  65.     cgiFormFileClose(file);
  66.     close(targetFile);
  67.     goto END;
  68.         FAIL:
  69.         fprintf(stderr,"Failed to upload");
  70.     return 1;
  71.     END:
  72.         printf("File %s has been uploaded",fileNameOnServer);
  73.         return 0;
  74. }

点击(此处)折叠或打开

  1. upload.html 源码

  2. <html>
  3. <head>
  4.     <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
  5.     <title>Test Upload</title>
  6.     <meta name="author" content="Jack">
  7. </head>
  8. <body>
  9. <form action="cgi-bin/upload.cgi" method="post" enctype="multipart/form-data" target="_blank">
  10.     <input type="file" name="file" value="" />
  11.     <input type="submit" name="submit" value="OK">
  12. </form>
  13. </body>
  14. </html>

实验结果先上图




cgi-bin 目录下也可以查看到 mxc_i2c.c 这个文件,且文件是对的。cgic的编程看起来要简洁很多,至少没有那么多printf语句了。
另外上面的链接中提到了对上传文件大小进行限制,相当于一个patch吧。先不测试这一点了,这里mark一下。算是对cgic有一个
直观的了解吧。关于库里面的函数接口,可以查看源码中附带的cgic.html 网页。

 

<>CGI +Ajax 实现动态网页                                                                               

实验环境:

PC 机 :windows 7

嵌入式主板:IMX287 , linux.2.6.31

PC机与嵌入式主板在同一局域网。

实验源码:cgi_ajax.rar
 cgi_ajax_settimeout.rar
.gif

  前面的实验均不能实现动态变化,例如实时获取服务器上的时间,采集到的温度值,湿度值等等实时变量。基于以上的目的,
cgi+ajax 就可以达到这样的目的。Ajax就是一个js文件,是用来给浏览器解析的,而不是嵌入式主控板boa服务器调用的。本实验
主要参考下面这个链接:

http://blog.csdn.net/huguohu2006/article/details/7755107

实验源码见附件

完了后结果如下,全是乱码。明显是中文显示的原因,前面的实验中均没有输出中文,所以没有这个问题。这种问题应该很容易定
位到是html网页中的。




点击(此处)折叠或打开

  1. <html>
  2.   <head>
  3.    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
  4.    <title>C+CGI+Ajax在mx287中的应用</title>
  5.    <script language="JavaScript" src="xmlhttpreq.js"></script>
  6.   </head>
  7.   <body>
  8.    <h3>获取服务器当前时间</h3>
  9.    <p>服务器当前时间是:<div id="current_time"></div></p>
  10.    <input type="button" value="提交" onclick="sender()" />
  11.   </body>
  12. </html>

修改了上面绿色部分。这个问题是编码格式带来的,汉字需要UTF-8。这个需要与浏览器配合,浏览器的编码也需要为UTF-8。
点击提交按钮后又出现了如下页面



同理可以想到,问题应该出现在CGI程序上。

点击(此处)折叠或打开

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <time.h>

  4. int main(void)
  5. {
  6.      time_t current;
  7.      struct tm *timeinfo;
  8.      time(&current);
  9.      timeinfo = localtime(&current);
  10.      //这一句一定要加,否则异步访问会出现页面异常
  11.      printf("Content-Type:text/html;charset=UTF-8 \n\n");
  12.      printf("%s", asctime(timeinfo));
  13. }

  也是修改了绿色部分,修改编码。验证了输出英文是没有问题的,如下。然后修改成输出时间信息,也是可以正常显示的。
但问题也来了,点击一次才会出现时间信息的更新。重新捋一捋,本次实验的目的是动态实现时间信息的自动更新,然而
并没有,那本次实验没有意义吗?当然也不是,万丈高楼平地起,前面的实验过程中充分利用了js 脚本,通过js脚本调用
CGI程序。




  上面的已经实验js脚本调用,接下来就来实现动态更新。在JavaScript 中也是有定时器的,利用定时器实现动态更新,
相对来说比较直接,也是容易实现的。参考过此帖子

在上面的实验基础上,更改代码如下:

点击(此处)折叠或打开

  1. /*
  2.   *异步访问提交处理
  3.  */
  4. function sender()
  5.  {
  6.      xhr = createXHR();
  7.      if(xhr)
  8.      {
  9.          xhr.onreadystatechange=callbackFunction;
  10.         //cgi_ajax后面跟个cur_time参数是为了防止Ajax页面缓存
  11.         xhr.open("GET", "cgi-bin/cgi_ajax?cur_time=" + new Date().getTime());
  12. //添加定时器,并且自己调用自己
  13.         setTimeout("sender()",1000) ;
  14.         xhr.send(null);
  15. // document.getElementById("current_time").value=xmlHttp.responseText;
  16.      }
  17.      else
  18.      {
  19.          //XMLHttpRequest对象创建失败
  20.         alert("浏览器不支持,请更换浏览器!");
  21.      }
  22.  }

  增加了绿色部分代码。在这次更新后,切忌清空浏览器缓存,由于这个问题,瞎折腾了半天。在IE, Chrome 上均测试过,
可以使用,实验结果如下GIF图:(结果显示不了GIF)



  到此为止,关于BOA的实验也告一段落了。整体跑通了后,如果想实现一些大点的项目可能还需要完善CGI程序的功能,
htmljs做得更完美,甚至最后还有可能需要配合数据库。当然这些相对来说都简单了,分层分工了。



阅读(6679) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~