BOA CGI移植与实例实验
--------------------------------------------------------------------------------------------------------------
-----------------由于长的发不了,分两篇吧,紧接上部分---------------------------------------------------------
--------------------------------------------------------------------------------------------------------------
点击 resu按钮后,出现如下页面,大大的Error 肯定就不对了。那么问题就来了。照着别人的做也不是什么问题也没有,
事非经过不知难。
这时候还是比较理智,get可以,post不行。表明链路等已经正确,应该是配置的问题,或者这位兄台的程序有问题。
想起来了error_log,查看了一下,如下:
没有看懂这些log,但发现了最后一句话 Permission denied 。联想前一实验的权限问题,修改完user group 就出现
如下界面了。
-
get源码
-
#include <stdio.h>
-
#include <stdlib.h>
-
int main(void)
-
{
-
char *data;
-
char a[10],b[10];
-
printf("Content-Type:text/html\n\n");
-
printf("\n");
-
printf("\n\n\n");
-
printf("\n");
-
printf("\n");
-
data = getenv("QUERY_STRING");
-
//http://192.168.7.254/cgi-bin/get?a=2&b=4
-
if(sscanf(data,"a=%[^&]&b=%s",a,b)!=2){
-
printf("Error parameters should be entered!\n");
-
}
-
else{
-
printf("a + b = %d\n",atoi(a)+atoi(b));
-
}
-
printf("");
-
printf("");
-
printf("\n");
-
printf(" \n");
-
printf("\n");
-
return 0;
-
}
sscanf 是对来自于变量的字符串进行输入操作,与scanf 类似。
QUERY_STRING 变量,在我的这次访问中,其实就上面注释部分的后半部分,a=2&b=3
返回参数数目为2,则表示正确解析。
关于sscanf参考如下:
/>
-
post 源码
-
#include <stdio.h>
-
#include <stdlib.h>
-
int main(void){
-
int len;
-
char *lenstr,poststr[20];
-
char m[10],n[10];
-
printf("Content-Type:text/html\n\n");
-
printf("\n");
-
printf("\n\n\n");
-
printf("\n");
-
printf("\n");
-
lenstr=getenv("CONTENT_LENGTH");
-
if(lenstr == NULL)
-
printf("Error parameters should be entered!\n");
-
else{
-
len=atoi(lenstr);
-
//http://192.168.7.254/cgi-bin/post
-
fgets(poststr,len+1,stdin);
-
if(sscanf(poststr,"m=%[^&]&n=%s",m,n)!=2){
-
printf("Error: Parameters are not right!\n");
-
}
-
else{
-
printf("m * n = %d\n",atoi(m)*atoi(n));
-
}
-
}
-
printf("");
-
printf("");
-
printf("\n");
-
printf("\n");
-
printf("\n");
-
fflush(stdout);
-
return 0;
-
}
上面的注释是可以看得到的,在网址中是没有类似于get时的变量及值的。其中fgets语句会让人有些疑虑,为什么是stdin 呢?
这是因为在boa 中stdin 已经重定向到了网页这边,这也是printf能输出html的原因。
CGI环境变量列表
SERVER-NAME:运行CGI序为机器名或IP地址。
SERVER-INTERFACE:WWW服务器的类型,如:CERN型或NCSA型。
SERVER-PROTOCOL:通信协议,应当是HTTP/1.0。
SERVER-PORT:TCP端口,一般说来web端口是80。
HTTP-ACCEPT:HTTP定义的浏览器能够接受的数据类型。
HTTP-REFERER:
发送表单的文件URL。(并非所有的浏览器都传送这一变量)
HTTP-USER-AGENT:发送表单的浏览器的有关信息。
GETWAY-INTERFACE:CGI程序的版本,在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-TYPE:POST发送,一般为applioation/xwww-form-urlencoded。
CONTENT-LENGTH:POST方法输入的数据的字节数。
关于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
-
cgi源码如下:
-
#include<stdio.h>
-
#include<string.h>
-
#include<unistd.h>
-
#include<fcntl.h>
-
#include<sys/stat.h>
-
#include"cgic.h"
-
#define BufferLen 1024
-
int cgiMain(void)
-
{
-
cgiFilePtr file;
-
int targetFile;
-
mode_t mode;
-
char name[128];
-
char fileNameOnServer[64];
-
char contentType[1024];
-
char buffer[BufferLen];
-
char *tmpStr=NULL;
-
int size;
-
int got,t;
-
cgiHeaderContentType("text/html");
-
//取得html页面中file元素的值,应该是文件在客户机上的路径名
-
if (cgiFormFileName("file", name, sizeof(name)) !=cgiFormSuccess)
-
{
-
fprintf(stderr,"could not retrieve filename/n");
-
goto FAIL;
-
}
-
cgiFormFileSize("file", &size);
-
//取得文件类型,不过本例中并未使用
-
cgiFormFileContentType("file", contentType, sizeof(contentType));
-
//目前文件存在于系统临时文件夹中,通常为/tmp,通过该命令打开临时文件。临时文件的名字与用户文件的名字不同,所以不能
-
//通过路径/tmp/userfilename的方式获得文件
-
if (cgiFormFileOpen("file", &file) != cgiFormSuccess)
-
{
-
fprintf(stderr,"could not open the file/n");
-
goto FAIL;
-
}
-
t=-1;
-
//从路径名解析出用户文件名
-
while(1)
-
{
-
tmpStr=strstr(name+t+1,"//");
-
if(NULL==tmpStr)
-
tmpStr=strstr(name+t+1,"/");//if "//" is not path separator, try "/"
-
if(NULL!=tmpStr)
-
t=(int)(tmpStr-name);
-
else
-
break;
-
}
-
strcpy(fileNameOnServer,name+t+1);
-
mode=S_IRWXU|S_IRGRP|S_IROTH;
-
//在当前目录下建立新的文件,第一个参数实际上是路径名,此处的含义是在cgi程序所在的目录(当前目录))建立新文件
-
targetFile=open(fileNameOnServer,O_RDWR|O_CREAT|O_TRUNC|O_APPEND,mode);
-
if(targetFile<0)
-
{
-
fprintf(stderr,"could not create the new file,%s/n",fileNameOnServer);
-
goto FAIL;
-
}
-
//从系统临时文件中读出文件内容,并放到刚创建的目标文件中
-
while (cgiFormFileRead(file, buffer, BufferLen, &got) ==cgiFormSuccess)
-
{
-
if(got>0)
-
write(targetFile,buffer,got);
-
}
-
cgiFormFileClose(file);
-
close(targetFile);
-
goto END;
-
FAIL:
-
fprintf(stderr,"Failed to upload");
-
return 1;
-
END:
-
printf("File %s has been uploaded",fileNameOnServer);
-
return 0;
-
}
-
upload.html 源码
-
-
<html>
-
<head>
-
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
-
<title>Test Upload</title>
-
<meta name="author" content="Jack">
-
</head>
-
<body>
-
<form action="cgi-bin/upload.cgi" method="post" enctype="multipart/form-data" target="_blank">
-
<input type="file" name="file" value="" />
-
<input type="submit" name="submit" value="OK">
-
</form>
-
</body>
-
</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网页中的。
-
<html>
-
<head>
-
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
-
<title>C+CGI+Ajax在mx287中的应用</title>
-
<script language="JavaScript" src="xmlhttpreq.js"></script>
-
</head>
-
<body>
-
<h3>获取服务器当前时间</h3>
-
<p>服务器当前时间是:<div id="current_time"></div></p>
-
<input type="button" value="提交" onclick="sender()" />
-
</body>
-
</html>
修改了上面绿色部分。这个问题是编码格式带来的,汉字需要UTF-8。这个需要与浏览器配合,浏览器的编码也需要为UTF-8。
点击提交按钮后又出现了如下页面
同理可以想到,问题应该出现在CGI程序上。
-
#include <stdio.h>
-
#include <stdlib.h>
-
#include <time.h>
-
-
int main(void)
-
{
-
time_t current;
-
struct tm *timeinfo;
-
time(¤t);
-
timeinfo = localtime(¤t);
-
//这一句一定要加,否则异步访问会出现页面异常
-
printf("Content-Type:text/html;charset=UTF-8 \n\n");
-
printf("%s", asctime(timeinfo));
-
}
也是修改了绿色部分,修改编码。验证了输出英文是没有问题的,如下。然后修改成输出时间信息,也是可以正常显示的。
但问题也来了,点击一次才会出现时间信息的更新。重新捋一捋,本次实验的目的是动态实现时间信息的自动更新,然而
并没有,那本次实验没有意义吗?当然也不是,万丈高楼平地起,前面的实验过程中充分利用了js 脚本,通过js脚本调用
CGI程序。
上面的已经实验js脚本调用,接下来就来实现动态更新。在JavaScript 中也是有定时器的,利用定时器实现动态更新,
相对来说比较直接,也是容易实现的。参考过此帖子
在上面的实验基础上,更改代码如下:
-
/*
-
*异步访问提交处理
-
*/
-
function sender()
-
{
-
xhr = createXHR();
-
if(xhr)
-
{
-
xhr.onreadystatechange=callbackFunction;
-
//cgi_ajax后面跟个cur_time参数是为了防止Ajax页面缓存
-
xhr.open("GET", "cgi-bin/cgi_ajax?cur_time=" + new Date().getTime());
-
//添加定时器,并且自己调用自己
-
setTimeout("sender()",1000) ;
-
xhr.send(null);
-
// document.getElementById("current_time").value=xmlHttp.responseText;
-
}
-
else
-
{
-
//XMLHttpRequest对象创建失败
-
alert("浏览器不支持,请更换浏览器!");
-
}
-
}
增加了绿色部分代码。在这次更新后,切忌清空浏览器缓存,由于这个问题,瞎折腾了半天。在IE, Chrome 上均测试过,
可以使用,实验结果如下GIF图:(结果显示不了GIF)
到此为止,关于BOA的实验也告一段落了。整体跑通了后,如果想实现一些大点的项目可能还需要完善CGI程序的功能,
html,js做得更完美,甚至最后还有可能需要配合数据库。当然这些相对来说都简单了,分层分工了。
阅读(6679) | 评论(0) | 转发(0) |