C语言CGI编程入门(一)

    CGI是指web服务器调用编程语言编写的程序的一个接口。比如我们可以编写一个用户注册的页面,用户将其输入的邮箱、用户名、密码输入并点击注册,此时浏览器就将用户输入的内容发送给了我们后台的CGI程序,我们的CGI程序接受到这些信息,可以对其进行处理。比如送入数据库、判断输入的信息是否合法等。

    主流的CGI程序用Perl编写,Perl是一款强大的脚本语言,不过我这里不太懂,我也不去比较某两个语言间的优劣。我说一下用C和C++如何编写CGI程序,告诉大家用C语言也能编写web应用程序,用C语言也能写一个网站。

    1.准备工作

    首先要先安装一款web服务器。我就用windows系统下的Apache,当然Linux下大同小异,可能需要设置的东西多一些。

    大家可以在apache官网下载最新版的Apache for Windows,天空也有下载:http://www.skycn.com/soft/1218.html。安装后打开安装目录,大致就是这样一些文件:

    点击查看原图

    看到那个“cgi-bin”了吗,这是默认的cgi程序目录。当然,我们也可以手动设置其位置:用记事本打开conf/httpd.conf,这是Apache的配置文件。找到类似下面这一行

ScriptAlias /cgi-bin/ "d:/Program Files (x86)/Apache Software Foundation/Apache2.2/cgi-bin/"

    "/cgi-bin/"表示web地址,比如默认是http://localhost/cgi-bin/,即访问cgi的根目录。"d:/Program Files (x86)/Apache Software Foundation/Apache2.2/cgi-bin/"表示对应的绝对路径。这应该不难理解,我们浏览器访问http://localhost/cgi-bin/就是代表访问了服务器上的相应的绝对路径。所以修改这个绝对路径,就可以指定我们的CGI程序存放的根目录。

    我这里就不改了,一会我们写好的CGI程序直接放在这个cgi-bin文件夹下,再通过http://localhost/cgi-bin/访问即可。

    2.开始写程序

    用VS2010新建一个控制台应用程序工程,我的就叫cgi_test。在main函数里写

	printf("Content-type:text/html\n\n");
	printf("hello world!!");

    当然也可以用C++的cout来代替printf输出。先别急着编译,我们先在工程上点右键,选择属性:

    点击查看原图

    在配置设置-常规中,更改输出目录为cgi-bin下。我就改成cgi-bin\test\,这样我们生成的可执行文件就会被放在这里。目标文件的扩展名我也顺便从exe改成cgi,如果不改,迅雷等下载可能会让你下载而不是让浏览器解析它。

    点击查看原图

    再就可以编译了。F7编译后,我们来到cgi-bin/test/中,就可以看到我们编译生成好的"cgi_test.cgi"文件。

    打开浏览器,输入http://localhost/cgi-bin/test/cgi_test.cgi,就可以看到hello world了:

    点击查看原图

    这就是我们的第一个cgi程序。

    3.怎么写一个CGI程序

    刚才写程序的工作是我来完成的,虽说那两个语句很简单,但有的同学会问为什么要这么写。

    我简单解释一下,第一个printf输出的"Content-type:text/html\n\n"是一个文件的标志,告诉浏览器以html的语法来解析此文件,而不是去下载它(注意末尾需要两个换行,即一个空行,这是标准)。只要我们需要输出内容到浏览器,都得加这一句话在最前面,记住就好。

    后面的printf就是输出到浏览器上的信息,注意需要用html的语法才能正常显示在浏览器上。比如换行,需要用<br />,而不是\n了。不懂的去学习关于html的知识(如果不学习html就别想做一个网站或web程序)。

    所以,只要通过printf,就可以将任何html代码输出在浏览器里。而且,因为是用C/C++写的程序,所以C/C++下的一切函数,都可以用在CGI程序里。(也包括windowsAPI)

    比如,用户填写好了注册表单,将信息传递给我的CGI程序,我就可以调用ODBC的函数,连接数据库,将信息写入数据库。也可以通过if判断句,来检查用户是否输入了非法信息。

    不过有同学又要问了,用户填写的信息怎么就传给我们的CGI程序了呢?程序又是怎么接受这些数据?

    4.接受GET或POST来的信息

    如果不知道GET和POST的意思,我建议你还是去看一下PHP。我这里只简单地提一下,我们新建一个html网页,在其中添加一个表单,其中有一个文本框和一个按钮,大致代码如下:

<form id="form" name="form" method="post" action="http://localhost/cgi-bin/test/cgi_test.cgi">
  <p>输入内容:
    <input type="text" name="user" id="user" />
  </p>
  <p>
    <input type="submit" name="submit" id="submit" value="提交" />
  </p>

</form>

    大家可以看到,form有个属性method,表示你用什么方式提交(post或get),action属性表示提交的地址。get方式提交,意思就是把提交的内容放在地址后面,用?隔开。post提交就是把数据放在数据包里发送给目标地址。我们在文本框内填入信息,点击按钮提交,我们填入的信息就会以相应方式发送到目标地址。

    C程序接受POST过来的信息比较简单。因为post来的信息都在输入流里,直接scanf或cin>>就能读取了。

    GET来的信息在地址栏里,我们需要用到一个C库中的函数:getenv,它的作用是获取环境变量,其中包括获取GET来的信息。(获取?后的所有内容:getenv("QUERY_STRING"))

    关于这个函数的所有用法我放在附件里,下载可查。

    5.做个示范

int _tmain(int argc, _TCHAR* argv[])
{
	printf("Content-type:text/html\n\n");
	printf("%s",getenv("QUERY_STRING")); //打印get获取的信息
	char szPost[256];
	gets(szPost);
    if(strcmp(szPost,))
            printf("%s",szPost); //打印post获取的信息
	return 0;
}

    用我们刚才的html代码来提交:

    填入内容:点击查看原图

    post方式获取的信息,注意地址栏:点击查看原图

    get方式获取的信息,注意地址栏:点击查看原图

    至于get方式获取的信息打印出来后面为什么有乱码,因为我顺便把没有信息的szPost也打印了。实际应用的时候应该先判断szPost中是否有信息再打印。


    今天写的够多了。大致C/C++处理CGI就是这样子,你可以发挥自己的想象,写出一些具有使用价值的程序。我们下次给大家讲一个库,通过这个库,可以很轻松的使用cgi编写web应用程序。

赞赏

喜欢这篇文章,扫码和我成为赞友!

评论

Ken 回复

博主写的很棒

实习生 回复

博主您好,如果我post过去的数据是2进制,cgi应该怎样接收呢,scanf有空格或者回车就结束了啊

phithon 回复

@实习生:这个应该要考虑的。你可以看看cgic库内部是怎么实现的。

白及 回复

好吧,真的挺欣赏你的,真是很积极阳光的技术宅童鞋~~~

落沐萧萧 回复

@白及:哈~学姐过奖了

砖机托板 回复

学习了 呵呵

黎健雄 回复

懂了一点点点点。
不过现在都流行PHP了吧。

落沐萧萧 回复

@黎健雄:我主要用C可以写一点木马、后门。PHP还是弱了。

captcha