嵌入式linux 项目开发(一)——CGIC编程
2019-07-12 17:46 发布
生成海报
嵌入式linux 项目开发(一)—— CGIC 编程
一、CGIC 简介
1、 CGI 简介
CGI( Common Gateway Interface )是外部应用扩展应用程序与 WWW 服务器交互的一个标准接口。按照 CGI 标准编写的外部扩展应用程序可以处理客户端浏览器输入的数据,从而完成客户端与服务器的交互操作。而 CGI 规范就定义了 Web 服务器如何向扩展应用程序发送消息,在收到扩展应用程序的信息后又如何进行处理等内容。通
过 CGI 可以提供许多静态的 HTML 网页无法实现的功能,比如搜索引擎、基于 Web 的数据库访问等等。
CGI的主要功能:
A、 分析数据,并自动校正一些有缺陷的浏览器发来的数据
B、透明接收用GET或 POST方法发来的From数据
C、能接受上传文件
D 、能够设置和接收cookies
E、用一致的方式处理From元素里的回车
F、提供字符串,整数,浮点数,单选或多选功能来接收数据
G、提供数字字段的边界检查
H、能够将CGI环境变量转化成C中的非空字符串
I、提供CGI程序的调试手段,能够回放CGI程序执行时的CGI状态
2、 BOA 与 CGI 工作机制
BOA和 CGI 的工作机制:
HTTP协议是 WWW 的基础,基于客户 / 服务器模型,服务器可以为分布在网络中的客户提供服务 。HTTP是 建立在 TCP/IP 协议之上的 “ 无连接 ” 协议,每次连接只处理一个请求。在 BOA服务器上,运行产着一个守护进程对端口进行监听,等待来自客户的请求。当一个请求到来时,将创建一个子进程为用户的连接服务。根据请求的不同,服务器返回 HTML 文件或者通过 CGI 调用外部应用程序,返回处理结果。服务器通过 CGI 与外部程序和脚本之间进行交互,根据客户端在进行请求时所采取的方法,服务器会收集客户所提供的信息,并将该部分信息发送给指定的 CGI 扩展程序。 CGI 扩展程序进行信息处理并将结果返回服务器,然后服务器
对信息进行分析,并将结果发送回客户端。
外部CGI程序与BOA服务器进行通信、传递有关参数和处理结果是通过环境变量、命令行参数和标准输入来进行的。服务器提供了客户端(浏览器)与 CGI 扩展程序之间的信息交换的通道。 CGI 的标准输入是服务器的标准输出,而 CGI 的标准输出是服务器的标准输入。客户的请求通过服务器的标准输出传送给 CGI 的标准输入, CGI 对信息进行处理后,将结果发送到它的标准输入,然后由服务器将处理结果发送给客户端。
CGIC是一个功能比较强大的支持 CGI 开发的标准 C 库,并支持 Linux , Unix 和 Windows 等多操作系统。
CGIC的主站点 http://www.boutell.com/cgic/
3、 URL简介
客户端浏览器向服务器发送数据采用编码的形式进行,编码就是 U RL编码。编码的主要工作是表单域的名字和值的转义,具体的做法为:每一对域和值里的空格都会被替换为一个加号( + )字符,不是字母或数字的字符将被替换为它们的十六进制数字形式,格式为 %HH 。 HH 是字符的 ASCII 十六进制值。 标签将被替换为 “%0D%0A” 。
信息是按它们在表单里出现的顺序排列的。数据域的名字和数据域的值通过等号 (= )字符连在一起。各对名 / 值再通过 “&” 字符连接在一起。经过这些编码处理之后,表单信号就整个成为一个连续的字符流,里面包含着将被送往服务器的全部信息。
因为表单输入信息都是经过编码后传递给脚本程序的,所以 CGI 扩展程序在使用这些参数之前必须对它们进行解码。
二、CGIC 编译配置
1、下载 CGIC 源码
tar -zxvf cgic206.tar.gz
2、修改 Makefile 文件
CC=arm-linux-gcc
AR=arm-linux-ar
RANLIB=arm-linux-ranlib
CFLAGS=-g -Wall -static
cgictest.cgi: cgictest.o libcgic.a
$(CC) $(CFLAGS) cgictest.o -o cgictest.cgi ${LIBS}
capture: capture.o libcgic.a
$(CC) $(CFLAGS) capture.o -o capture ${LIBS}
3、编译
make
编译得到的文件
libcgic.a:CGIC 库
capture:调试辅助程序
cgictest.cgi:测试程序
4、安装CGIC
make install
CGIC安装路径为
libcgic.a 安装在 /usr/local/lib
cgic.h 安装在 /usr/local/include
CGIC库安装后就可以使用 CGIC 编程了
5、 CGIC 文件的移植
将capture和cgictest.cgi拷贝到开发板的/var/www/cgi-bin目录
6、运行cgi 程序
在客户端浏览器运行http://192.168.6.210/cgi-bin/cgictest.cgi
如果正常显示网页内容,则BOA 与 CGIC 可以正常工作
三、CGIC 移植过程中错误的解决
1、 html 网页可以运行, CGI 程序运行报错
Boa服务器报错: cgi_header: unable to find LFLF
客户端浏览器报错: 502 Bad Gateway
The CGI was not CGI/1.1 compliant.
解决方法:静态编译cgi程序
arm-linux-gcc -o hello.cgi hello.c -static
四、CGIC 编程
1、 CGI通信方式
当有数据从客户端浏览器传到 Web 服务器后,web服务器会根据传送的类型(基本有二类: GET/POST ),将接收到的数据传入 QUERY_STRING 或变量中, CGI 程序可以通过标准输入,在程序中接收web服务器接收的 数据。当要向浏览器发送信息时,只要向 Web 服务器发送特定的文件头信息,即可通过标准输出将信息发往 Web 服务器, Web 服务器处理完由 CGI 程序发来的信息后就会将信息发送给浏览器。
2、 接收数据
用 GE T方式接收到的数据保存在 Web 服务器的 QUERY_STRING 变量里,而通过 POST 方式接收到的数据是保存在 Web 服务器变量里。两种数据接收方式的区别是:以 GET 方式接收的数据是有长度限制,而用 POST 方式接收的数据是没有长度限制的;以 GET 方式发送数据,可以通过 URL 的形式来发送,但 POST 方式发送的数据必须要通过 Form 才到发送。
3、 CGI变量
char *cgiServerSoftware
服务器软件名称,或者一个空的字符串
char *cgiServerName
返回服务器名称或空
char *cgiGatewayInterface
网关接口(通常是 CGI/1.1)或空
char *cgiServerProtocol
网络协议(usually HTTP/1.0)或空
char *cgiServerPort
服务器端口(usually 80),或空
char *cgiRequestMethod
请求方式(usually GET or POST)或空
char *cgiPathInfo
指出附加虚拟路径
char *cgiPathTranslated
指出附加虚拟路径并由服务器转为本地路径
char *cgiscriptName
调用程序的名字
char *cgiQueryString
包含GET-method请求或者 标签。不需解析,除非用 标签,通常由CGIC函数库自动解析。
char *cgiRemoteHost
从浏览器返回客户主机的名字
char *cgiRemoteAddr
从浏览器返回客户的IP地址
char *cgiAuthType
返回用户授权信息
char *cgiRemoteUser
鉴别用户cgiAuthType.
char *cgiRemoteIdent
返回用户的名字(用户通过用户坚定协议)
char *cgiContentType
返回MIME内型
char *cgiAccept
参考 cgiHeaderContentType() cgiUserAgent
char *cgiUserAgent
获取的用户浏览器信息
char *cgiReferrer
指向用户访问的URL.
int cgiContentLength
表单或查询数据的字节被认为是标准的.
FILE *cgiOut
CGI输出。cgiHeader函数,象cgiHeaderContentType,首先被用于输出mime头;用于 fprintf() 和fwrite()。cgiOut通常相当于stdout。
FILE *cgiIn
CGI输入
4、 CIGC 库主要函数
用一般 ANSI C 或 C++ 编译器就可以编译CGIC程序 , 与 C 程序不同的是,用CGIC写的源码其主函数是 cgiMain(), 而不是通常的 main 。 CGIC的函数库会自动把 cgiMain 连接到相应的 main 上。
CGIC库主要函数说明:
cgiFormResultType cgiFormString( char *name, char *result, int max)
用于从输入域中 copy 字符串。将域名 max-1 字节中的字符 copy 到缓冲区 result 。若域不存在,则 copy 一个空串到 result 缓冲区。在此函数中所有的新行由换行符代表。
cgiFormResultType cgiFormStringNoNewlines( char *name, char *result, int max)
与cgiFormString函数相似,只是所有的CR和LF都被去掉。
cgiFormResultType cgiFormStringSpaceNeeded( char *name, int *length)
返回指向name的字符串的长度,并将长度放入length中。
cgiFormResultType cgiFormStringMultiple( char *name, char ***ptrToStringArray)
若同一名字有多个输入域,或域中的字符串可以动态变化,使用本函数。它把名为name的所有输入域的值放在prtToStringArray中。
void cgiStringArrayFree(char **stringArray)
释放了分配给stringArray的内存。
cgiFormResultType cgiFormInteger( char *name, int *result, int defaultV)
从输入域中取出整数放入result中。
cgiFormResultType cgiFormIntegerBounded( char *name, int *result, int min, int max, int defaultV)
若输入域中的整数在界限内则取出并放入result中。
cgiFormResultType cgiFormDouble( char *name, double *result, double defaultV)
从输入域中取出浮点数放入result中。
cgiFormResultType cgiFormDoubleBounded( char *name, double *result, double min, double max, double defaultV)
若输入域中的浮点数在界限内则取出并放入result中。
cgiFormResultType cgiFormSelectSingle( char *name, char **choicesText, int choicesTotal, int *result, int defaultV)
取出复选框(跟在select语句之后的),把选择的名字copy到choicesText,把选择的个数copy到choicesTotal,把当前的选择copy到result。
cgiFormResultType cgiFormSelectMultiple( char *name, char **choicesText, int choicesTotal, int *result, int *invalid)
与cgiFormSelectSingle类似,只指向整型数组的result代表了选择的项。
cgiFormResultType cgiFormCheckboxSingle( char *name)
若复选框被选中,则函数返回cgiFormSuccess,否则返回cgiFormNotFound。
cgiFormResultType cgiFormCheckboxMultiple( char *name, char **valuesText, int valuesTotal, int *result, int *invalid)
与cgiFormCheckboxSingle类似,但它处理同一名字有多个复选框的情况。name指向复选框的名字;valuesText指向包含有每个复选框中参数的一个数组;valuesTotal指向复选框的总数;result是一个整型数组,每个复选框选中的用1代表,没选中的用0代表。
cgiFormResultType cgiFormRadio( char *name, char **valuesText, int valuesTotal, int *result, int defaultV)
与cgiFormCheckboxMultiple相似,只是这里是单选按钮而不是复选框。
void cgiHeaderLocation(char *redirectUrl)
重定向到redirectUrl指定的URL。
void cgiHeaderStatus(int status, char *statusMessage)
输出状态代码status和消息statusMessage。
void cgiHeaderContentType(char *mimeType)
用于告知浏览器返回的是什么类型的文档。在任何向浏览器输出之前被调用,否则将出错或浏览器不能识别。
cgiEnvironmentResultType cgiWriteEnvironment(char *filename)
本函数把当前CGI环境写入filename文件中以便以后调试时使用
cgiEnvironmentResultType cgiReadEnvironment(char *filename)
本函数从filename文件中读取CGI环境以便用来调试。
5、 CGI结果编码
CGIC结果编码参考:
cgiFormSuccess
提交信息成功
cgiFormTruncated
删除部分字节.
cgiFormBadType
错误的输入信息(没有按要求)
cgiFormEmpty
提交信息为空.
cgiFormNotFound
提交信息没有找到.
cgiFormConstrained
数字属于某个特定的范围,被迫低于或高于适当范围。
cgiFormNoSuchChoice
单一选择提交的值是不被接受。通常说明表但和程序之间存在矛盾。
cgiEnvironmentIO
从CGI环境或获取的文件读或写的企图失败,报出I/O的错误。
cgiEnvironmentMemory
从CGI环境或获取的文件读或写的企图失败,报出out-of-memory的错误。
cgiEnvironmentSuccess
从CGI环境或获取的文件读或写的企图成功。
6、 CGI环境变量
REQUEST_METHOD 请求类型,如 “GET”或 “POST”
CONTENT_TYPE 被发送数据的类型
CONTENT_LENGTH 客户端向标准输入设备发送的数据长度,单位为字节
QUERY_STRING 查询参数,如 “ id=10010&sn=liigo”
SCRIPT_NAMECGI 脚本程序名称
PATH_INFOCGI 脚本程序附加路径
PATH_TRANSLATEDPATH_INFO 对应的绝对路径
REMOTE_ADDR 发送此次请求的主机IP
REMOTE_HOST 发送此次请求的主机名
REMOTE_USER 已被验证合法的用户名
REMOTE_IDENTWEB 服务器的登录用户名
AUTH_TYPE 验证类型
GATEWAY_INTERFACE 服务器遵守的CGI版本,如 :CGI/1.1
SERVER_NAME 服务器主机名、域名或IP
SERVER_PORT 服务器端口号
SERVER_PROTOCOL 服务器协议,如 :HTTP/1.1
DOCUMENT_ROOT 文档根目录
SERVER_SOFTWARE 服务器软件的描述文本
HTTP_ACCEPT 客户端可以接收的MIME类型,以逗号分隔
HTTP_USER_AGENT 发送此次请求的web浏览器
HTTP_REFERER 调用此脚本程序的文档
HTTP_COOKIE 获取COOKIE键值对,多项之间以分号分隔,如 :key1=value1;k e y2=value2
7、输出标头
cgiHeaderContentType , 在任何向浏览器输出之前被调用 ,否则将出错或浏览器不能识别。
8、处理输入文本
void Name() {
char name[81];
cgiFormStringNoNewlines("name", name, 81);
fprintf(cgiOut, "Name: %s
", name);
}
获取并 显示由用户输入的 name
9、处理单一复选框
1
2
3
4
5
6
7
8
9
10
11
void
Hungry()
{
if
(cgiFormCheckboxSingle(
"hungry"
) == cgiFormSuccess)
{
fprintf
打开微信“扫一扫”,打开网页后点击屏幕右上角分享按钮