由于在项目的网络开发中需要使用CGI脚本来实现通讯。通过本地的httpserver将需要处理的信息传送给CGI脚本,通过CGI脚本中预先实现的功能来处理。
在项目的实现过程中使用了开源的CGIC,是C语言CGI库函数。其中包括:
cgic.h:头文件;
cgic.c:CGIC的源代码文件;
capture.c:用于调试CGI程序的工具;
使用CGIC实现的基本思路:
通过分析CGIC的代码,在cgic.c的代码可以看出,它定义了main函数。是通过cgic.C中的mian函数中来调用实现特定功能的函数,在我们功能实现的函数cgictest.c中定义了一个cgiMain函数。对于使用CGIC编写的CGI 程序,都是从cgic.c中的代码进入,在库函数完成了一系列必要的操作(比如解析参数、获取系统环境变量)之后,它才会调用我们自己定义的代码(定义的 cgiMain进入)。
另外一点比较有意思的地方就是,cgi脚本程序输出给httpserver的方式都是使用printf把页面一行一行地打印出来,比如cgictest.c中的这一段代码:
fprintf(cgiOut, "<textarea NAME=\"address\" ROWS=4COLS=40>\n");
第一个参数cgiOut实际上就是stdin,所以我们可以直接使用printf,而不必使用fprintf。
使用C语言编写cgi脚本的时候还要声明自己输出的数据类型(声明文档类型),如:
cgiHeaderContentType("text/html");//html文档
cgiHeaderContentType("text/plain");//文本类型
cgiHeaderContentType("application/json");//json格式的数据
主要目的告诉浏览器,这次传来的数据是什么类型,是一个HTML文档,还是一个bin文件。如果是个HTML文档,就通过浏览器窗口显示,如果是一个bin(二进制)文件,则打开下载窗口,让用户选择是否保存文件以及保存文件的路径。
其中http数据包中请求的数据在本地httpserver和cgi脚本中通过环境变量获取:
cgiGetenv(&cgiServerSoftware,"SERVER_SOFTWARE");
cgiGetenv(&cgiServerName,"SERVER_NAME");
cgiGetenv(&cgiGatewayInterface,"GATEWAY_INTERFACE");
cgiGetenv(&cgiServerProtocol,"SERVER_PROTOCOL");
cgiGetenv(&cgiServerPort,"SERVER_PORT");
cgiGetenv(&cgiRequestMethod,"REQUEST_METHOD");
cgiGetenv(&cgiPathInfo,"PATH_INFO");
cgiGetenv(&cgiPathTranslated,"PATH_TRANSLATED");
cgiGetenv(&cgiScriptName,"SCRIPT_NAME");
cgiGetenv(&cgiQueryString,"QUERY_STRING");
cgiGetenv(&cgiRemoteHost,"REMOTE_HOST");
cgiGetenv(&cgiRemoteAddr,"REMOTE_ADDR");
cgiGetenv(&cgiAuthType,"AUTH_TYPE");
cgiGetenv(&cgiRemoteUser,"REMOTE_USER");
cgiGetenv(&cgiRemoteIdent,"REMOTE_IDENT");
在cgi脚本中可以通过 fgets(input,cgiContentLength+1, stdin); 可以获取到content中的数据。