CGI是一种比较古老的动态WEB技术,现在几乎没有直接使用CGI程序的WEB服务器了,但是作为学习研究,还是可以的。
CGI的原理是WEB服务器收到浏览器的请求时,执行对应的CGI程序,其本质是一个EXE文件。
这个EXE文件可以通过环境变量获取浏览器的请求信息,然后把页面数据输出到标准输出流(stdout);
然后WEB服务器会把这些数据返回给浏览器。
根据这些信息,我写了一个简单的CGI程序,把浏览器的UA信息返回给浏览器,并把访问记录保存在服务器。
需要注意的是,在输出页面数据的时候,需要先给HTTP响应的头部数据,比如Content-Type: text/html,再接一个空行。
这个空行是HTTP协议头部结束的标志,后面的数据作为HTTP响应的BODY数据。
我们的HTML页面数据就作为HTTP协议的BODY。
/*
CGI环境变量
CONTENT_TYPE 这个环境变量的值指示所传递来的信息的MIME类型。目前,环境变量CONTENT_TYPE一般都是:application/x-www-form-urlencoded,他表示数据来自于HTML表单。
CONTENT_LENGTH 如果服务器与CGI程序信息的传递方式是POST,这个环境变量即使从标准输入STDIN中可以读到的有效数据的字节数。这个环境变量在读取所输入的数据时必须使用。
HTTP_COOKIE 客户机内的 COOKIE 内容。
HTTP_USER_AGENT 提供包含了版本数或其他专有数据的客户浏览器信息。
PATH_INFO 这个环境变量的值表示紧接在CGI程序名之后的其他路径信息。它常常作为CGI程序的参数出现。
QUERY_STRING 如果服务器与CGI程序信息的传递方式是GET,这个环境变量的值即使所传递的信息。这个信息经跟在CGI程序名的后面,两者中间用一个问号'?'分隔。
REMOTE_ADDR 这个环境变量的值是发送请求的客户机的IP地址,例如上面的192.168.1.67。这个值总是存在的。而且它是Web客户机需要提供给Web服务器的唯一标识,可以在CGI程序中用它来区分不同的Web客户机。
REMOTE_HOST 这个环境变量的值包含发送CGI请求的客户机的主机名。如果不支持你想查询,则无需定义此环境变量。
REQUEST_METHOD 提供脚本被调用的方法。对于使用 HTTP/1.0 协议的脚本,仅 GET 和 POST 有意义。
SCRIPT_FILENAME CGI脚本的完整路径
SCRIPT_NAME CGI脚本的的名称
SERVER_NAME 这是你的 WEB 服务器的主机名、别名或IP地址。
SERVER_SOFTWARE 这个环境变量的值包含了调用CGI程序的HTTP服务器的名称和版本号。例如,上面的值为Apache/2.2.14(Unix)
*/
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
static char local_string[1024];
const char * get_env_str(const char *name)
{
size_t sz;
getenv_s(&sz, local_string, 1024, name);
return local_string;
}
const char * get_tim_str(void)
{
struct tm tm;
time_t t;
t = time(NULL);
localtime_s(&tm, &t);
sprintf_s(local_string, 1024, "%04d-%02d-%02d %02d:%02d:%02d", tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec);
return local_string;
}
void main(void)
{
FILE *fp;
fopen_s(&fp, "access.txt", "a+");
if(fp != NULL)
{
fprintf(fp, "[%s]", get_tim_str());
fprintf(fp, "[%s]", get_env_str("REMOTE_ADDR"));
fprintf(fp, "[%s]", get_env_str("HTTP_USER_AGENT"));
fprintf(fp, "\n");
fclose(fp);
}
printf("Content-Type: text/html\n");
printf("\n");
printf("<html>");
printf("<head><meta charset=\"gbk\"/>");
printf("<title>浏览器检测</title>");
printf("</head>");
printf("<body>");
printf("<table>");
printf("<tr><td align=\"right\">浏览器UA:</td><td>%s</td></tr>", get_env_str("HTTP_USER_AGENT"));
printf("<tr><td align=\"right\">来访者IP:</td><td>%s</td></tr>", get_env_str("REMOTE_ADDR"));
printf("<tr><td align=\"right\">系统时间:</td><td>%s</td></tr>", get_tim_str());
printf("</body>");
printf("</html>");
}
编译为index.exe,然后放到WEB服务器根目录,打开浏览器访问就可以看到数据了: