主机环境:RedHat9
交叉编译器:arm-linux-gcc version 4.3.2
平台:s3c2440
(一) 编译boa
从Boa的官方网站 http://www.boa.org/ 上下载了它的发行版本源码,版本号为0.94.13。先把源码解压,调出超级终端并执行:
# tar xzf boa-0.94.13.tar.gz
# cd boa-0.94.13/src
生成MakeFile文件
#./configure
修改Makefile文件,找到CC=gcc,将其改成CC=arm-linux-gcc,再找到CPP = gcc -E,将其改成CPP = arm-linux-gcc -E,并保存退出。
然后运行make进行编译,这时出现如下错误:
“ util.c: 100: 1: pasting “t” and “->” does not give valid preprocessing token make ”的错误提示,
改动 compat.h 文件:
#define TIMEZONE_OFFSET(foo) foo##->tm_gmtoff
改为:
#define TIMEZONE_OFFSET(foo) foo->tm_gmtoff
编译成功。
另外,还需要修改一处src/log.c
注释掉
if (dup2(error_log, STDERR_FILENO) == -1) {
DIE("unable to dup2 the error log");
}
为:
/*if (dup2(error_log, STDERR_FILENO) == -1) {
DIE("unable to dup2 the error log");
}*/
否则会出现错误:
log.c:73 unable to dup2 the error log:bad file deor
最后优化调用交叉编译器的strip命令将调试信息剥去,得到的最后程序只有约60KB大小。
# make
# arm-linux-strip boa
(二) 配置boa
安装完Boa软件后,需要对Boa进行配置,其配置文件是boa.conf,这个文件在源代码中有,将其拷贝到嵌入式Linux根文件系统的/etc/boa目录下。然后对这个文件几个重要的地方进行如下修改[2]。
#[3]监听的端口号,缺省都是80,不做修改
Port 80
# 调用的IP地址,注释掉,这样表明绑定到INADDR_ANY,通配于服务器的所有IP地址。不设定静态固定的服务器地址。
#Listen 192.68.0.5
#设定那个Linux用户组的哪个用户,对Boa拥有权限
User root
Group root
#错误日志文件。设计路径在/dev/console下。
ErrorLog /dev/console
#访问日志文件。设置为/dev/null意味关闭AccessLog功能,启动服务器时不载入日志文件。
AccessLog /dev/null
#服务器名字
ServerName friendly-arm
# HTML文档的主目录,访问的页面即放在这个目录下。
DocumentRoot /www
#HTML目录默认索引文件名。
DirectoryIndex index.html
#一个连接所允许的HTTP持续作用请求最大数目。
KeepAliveMax 1000
#HTTP持续作用中服务器在两次请求之间等待的时间数,以秒为单位。
KeepAliveTimeout 10
#指明mime.types[4]文件位置。
MimeTypes /etc/mime.types
#文件扩展名没有或未知的话,使用的缺省 MIME 类型。
DefaultType text/plain
#提供 CGI 程序的 PATH 环境变量值。
CGIPath /bin:/usr/bin:/usr/sbin:/sbin
#指明 CGI 脚本的虚拟路径对应的实际路径, /www/cgi-bin/ 是我的根文件系统的目录。
ScriptAlias /cgi-bin/ /www/cgi-bin/
拷贝主机 /etc/mime.types 文件到根文件系统的 etc 目录下。
(三) 测试与出错处理
1 、静态网页测试
将一静态网页放置到HTML文档的主目录/www下,为了方便文件名修改为index.html,并在浏览器中输入目标板ip如http://192.168.1.200将出现静态网页。
2、cgi测试
首先,编写Helloworld.c程序
int main(void)
{
printf("Content-type:text/html\n\n"); //这句一定要加上
printf(" Hello,world.");
exit(0);
}
交叉编译arm-linux-gcc -o helloworld.cgi helloworld.c
将helloworld.cgi复制到/www/cgi-bin/目录下,注意执行权限,并在浏览器中输入http://192.168.1.200/cgi-bin/ helloworld.cgi即可看到相应的网页。
(四) cgi编程
动态网页的设计有很多方法,CGI是其中之一。Boa服务器支持cgi,这里介绍两种方式利用cgi完成客户端与服务器的通信。
首先了解cgi基本原,CGI全称是“公共网关接口”(Common Gateway Interface),HTTP服务器本地或远程应用程序通信的一种接口,其程序须运行在网络服务器上。在物理上,CGI是一段程序,它运行在Server上,提供同客户端 Html页面的接口。这样说大概还不好理解。那么我们看一个实际例子: 现在的个人主页上大部分都有一个留言本。留言本的工作是这样的:先由用户在客户端输入一些信息,如名字之类的东西。接着用户按一下“留言”(到目前为止工作都在客户端),浏览器把这些信息传送到服务器的CGI目录下特定的cgi程序中,于是cgi程序在服务器上按照预定的方法进行处理。在本例中就是把用户提交的信息存入指定的文件中。然后cgi程序给客户端发送一个信息,表示请求的任务已经结束。此时用户在浏览器里将看到“留言结束”的字样。整个过程结束。
n CGI工作的主要流程是:
1.一个用户请求激活一个CGI应用程序;
2.CGI应用程序将交互主页里用户输入信息提取出来;
3.将用户输入的信息传给服务器主机应用程序(如数据库查询〕;
4.将服务器处理结果通过HTML文件返回给用户;
5.CGI进程结束。
n HTML语言与HTML表单
HTML(超文本标记语言)是用来创建与平台无关的超文本文档的简单标记语言,踟[MI,能够用来标记超文本消息、邮件、文档、超媒体、菜单选项、数据库查询结果以及有内嵌图形的简单结构文档。HTML为文档编码,包括要显示的文本、文本如何格式化的信息、要显示的图片名字(不是图片自身)、以及其他重要信息。连接到一个网页时,Web浏览器(如IE)就在内存中按照HTML的结构“构造”该网页,然后在屏幕上显示组装好的网页。
通常浏览器只能通过HTML请求从服务器获取静态网页进行浏览,如果用户需要通过浏览器提交一些数据给服务器进行处理并返回结果以达到交互的效果则要用到HTML表单。HTML表单是用户通过浏览器提交数据为主要输入手段,它由普通文字、标记和一些称为“控件”的特殊元素(如复选框、单选按钮、菜单等)以及控件上的标签组成。用户通过填写或选择控件内容来输入数据,最后提交给服务器进行处理。
下面是一个表单的示例:
FORM的一些参数解释如下:
1. action指定了调用的CGI脚本
2. methed定义了表单被提交的方法。methed有两种,GET和POST。GET是CGI默认的传输方法,用户输入的数据会附在URL之后传给Web服务器。POST方法传递数据时,服务器端CGI处理程序会从SID躺中接收传输入数据。
3. reset的外观和submit相似,不过一旦用户按下它,这个form中的所有输入值都会被清除,或者是回到初始值。
n CGI的工作机制
上一节讲到浏览器提交数据需要用到HTML表单。那么服务器端是如何对这些数据进行识别和处理呢,这就需要用到CGI,通过CGI可以宪成浏览器与WEB服务器之间的信息交互。
CGI(common gateway interface)WEB 服务器和运行在服务器端的外部程序之间的一个接口规范,按照这个规范编写并运行的外部程序就叫做CGI程序,其目的是实现Web服务器与客户端浏览器之间的动态交互。CGI程序通过由Web服务器来调用实现和WEB浏览器之间的交互,如下图所示,Web服务器将WEB浏览器发送来的信息,传送给CGI程序,由CGI程序进行处理,CGI程序在处理完后将响应结果再回送给Web服务器,然后由Web服务器发送到Web浏览器。如果需要调用其他外部应用如数据库服务等,均由CGl程序去与外部应用进行交互.
浏览器与Web服务器的具体交互过程如下:
(1)客户机使用TCP/IP协议,与服务器建立连接,发送URL请求;
(2)Web服务器到相应的目录中调用CGI程序,使用客户机传递的参数作为CGI程序的参数,而CGI程序调用相应的外部程序完成操作;
(3)CGI程序以能被识别的格式返回处理结果给HTTP服务器;
(4)Web服务器将数据返回客户机处理,显示CGI执行结果。
CGI程序与Web服务器进行通信、传递有关参数和处理结果是通过命令行参数、标准输出、环境变量来实现的。如下图所示,CGI的标准输入(STDIN)是服务器的标准输出(STDOUT),而CGI的标准输出则是服务器的标准输入。客户的请求信息通过服务器的标准输出传送绘CGI的标准输入,CGI对信息进行处理后,将结果发送到它的标准输出,也就是服务器的标准输入,然后由服务器将处理结果发送给客户端。这里以boa为例,整个通信流程图如下所示:
同时,CGI程序可以通过环境变量获取Web服务器传递过来的用户数据,常见的环境变量有:
1. SERVER-NAME:运行CGI序为机器名或IP地址。
2. SERVER-INTERFACE:WWW服务器的类型,如:CERN型或NCSA型。
3. SERVER-PROTOCOL:通信协议,应当是HTTP/1.0。
4. SERVER-PORT:TCP端口,一般说来web端口是80。
5. HTTP-ACCEPT:HTTP定义的浏览器能够接受的数据类型。
6. HTTP-REFERER: 发送表单的文件URL。(并非所有的浏览器都传送这一变量)
7. HTTP-USER-AGENT:发送表单的浏览器的有关信息。
8. GETWAY-INTERFACE:CGI程序的版本,在UNIX下为 CGI/1.1。
9. PATH-TRANSLATED: PATH-INFO中包含的实际路径名。
10. PATH-INFO:浏览器用GET方式发送数据时的附加路径。
11. SCRIPT-NAME: CGI程序的路径名。
12. QUERY-STRING:表单输入的数据,URL中间号后的内容。
13. REMOTE-HOST:发送程序的主机名,不能确定该值。
14. REMOTE-ADDR:发送程序的机器的IP地址。
15. REMOTE-USER:发送程序的人名。
1) 利用shell脚本获取QUERY_STRING环境变量
通常这种方式适用于使用get方法提交的表单,post方法提交的表单要通过标准输出获取。但是对于boa服务器两种方式效果是一样的,即使采用post方式url中依然能获取相应的信息。典型的shell程序如下(友善的led测试脚本,位于/www/leds.cgi):
#!/bin/sh
type=0
period=1
case $QUERY_STRING in
*ping*)
type=0
;;
*counter*)
type=1
;;
*stop*)
type=2
;;
esac
case $QUERY_STRING in
*slow*)
period=0.25
;;
*normal*)
period=0.125
;;
*fast*)
period=0.0625
;;
esac
/bin/echo $type $period > /tmp/led-control
echo "Content-type: text/html; charset=gb2312"
echo
/bin/cat led-result.template
exit 0
网页中将要提交的表单action设置为leds.cgi即可。即
<td colspan="2" align="center"><form method="post" action="leds.cgi" name="LED-TEST">
这种方式通信的形式如下所示:
2) 利用cgic库编程动态网页
CGI的输出包括多个头部信息和一个数据体,两者之间用一个空行隔开。其中必须包含一个头部信息,如果带有数据体,则要求有Content-type,即MIME类型。MIME为Multipurpose Internet Mial Extension protocol的缩写,即多用途网际邮件扩充协议,它设计的最初目的是为了在发送电子邮件时附加多媒体数据,让邮件客户程序能根据其类型进行处理。当它被HTTP协议支持之后,它的意义就更为重要了。它使得HTTP不仅能传输普通的文本,而且能传输声音、视频等数据。MIME类型由两部分组成,前面是数据的大类别,后面定义具体的种类。常见的MIME类型如下表所示:
CGI程序一般由以下三部分构成:
(1)数据解码部分:通过表单输入、由浏览器传送给服务器的数据都是经过URL编码的,必须进行解码。如果不需要处理表单输入,则该部分省略。
(2)数据头部分:必须包含这一部分作为第一个输出行,该行后必须有一空格行。该行可以是下列三种之一:
ü 数据类型,如:Content-type:text/html
ü 地址类型(Location),如:location://www.kernel.org
ü 状态类型(Status),如:status:200 OK
(3)CGI程序主体部分。
对通过表单输入的数据进行处理,并输出到标准输出。
综上所述,CGI程序的功能是获取Web服务器传送的数据,解码处理后,根据用户的要求进行其它的操作。一般是生成动态Web页面或者调用其它的应用服务。
从原理上说,CGI程序设计可以采用任何读写标准输入,输出的语言,比如C/C++、Perl、Java等。但在嵌入式系统中,C语言是一个首选的工具语言。
这里利用设计好的一个cgic库来进行cgi的相关操作
CGIC是一个支持CGI开发的开放源码的标准C库。移植比较简单。
1、下载源码
http://www.boutell.com/cgic/上下载源码,当前最新版本是2.05
tar xzf cgic205.tar.gz(实际下载到的是.tar.tar,一样)
2、修改Makefile文件
修改 CC = gcc为 CC = /usr/local/arm/2.95.3/bin/arm-linux-gcc
修改 AR = ar为 AR = /usr/local/arm/2.95.3/bin/arm-linux-ar
修改 RANLIB = arnlib为 RANLIB = /usr/local/arm/2.95.3/bin/arm-linux-ranlib
修改 gcc cgictest.o -o cgictest.cgi ${LIBS}为 $(CC) $(CFLAGS) cgictest.o -o cgictest.cgi ${LIBS}
修改 gcc capture.o -o capture ${LIBS}为 $(CC) $(CFLAGS) capture.o -o capture ${LIBS}
3、编译
make编译,得到CGIC库libcgic.a
4、验证
将capture和cgictest.cgi复制到主机的/var/www/cgi-bin目录下,IE输入http://192.168.1.200/cgi-bin/cgictest.cgi,可以看到cgi的测试画面
注意:拷贝至目标板上后,必须更改其属性chmod 755 *
cgictest.cgi是cigic的一个例程,入口在cgimain,参考cgictest.c可以编写出其他的动态网页。需要注意的是fprintf("Content-type:text/html\n\n"); //这句一定要加上。