http的GET和POST
本文主要内容
1、 GET和POST方法介绍
2、 源代码分析
3、 结果分析
4、 例子
参考及引用:
http://www.cnblogs.com/zhijianliutang/archive/2012/09/23/2698860.html
http://www.cnblogs.com/liuzhang/p/3929198.html
http://www.cnblogs.com/Daniel-G/p/3995854.html
-----------------------------------------------------------------------------------------------------------------
1、GET和POST方法介绍
html发送表单给服务器常用方法有两种:GET和POST。
<1> GET方法发送给服务器的数据保存在服务器的QUERY_STRING环境变量中。读取这个环境变量的值,就可以获得数据。发送的数据就直接接在html信息头的后面,作为数据的一部分,这个后面会说明。
<2> POST方法的数据是放在发送过去的信息体中。其数据的长度保存在服务器的CONTENT_LENGTH环境变量中,数据被重定向到了标准输入,只要从标准输入读取CONTENT_LENGTH长度的数据即可。读取之后提取其中有用的数据。
2、源代码
<1> html
如下,是我写的网页,action属性指定接收并处理这个表单的函数,method指定表单发送的方法。文件名:button.html
1 <html> 2 <form action="http://192.168.1.112/cgi-bin/button.cgi" method="get"> 3 <input type="submit" name="button1" value="up"/> 4 <input type="submit" name="button2" value="down"/> 5 <input type="submit" name="button3" value="left"/> 6 <input type="submit" name="button4" value="right"/> 7 </form> 8 </html>
<2> 使用c语言写的cgi,文件名button.c。
1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <string.h> 4 5 char *getcgidata(FILE *fp, char *req_method) 6 { 7 char *input; 8 int length; 9 10 /* GET */ 11 if (strcmp(req_method, "GET") == 0) { 12 /* get方法的数据放在QUERY_STRING中 */ 13 input = getenv("QUERY_STRING"); 14 /* 将结果打印到浏览器中 */ 15 printf("<p>input:%s</p>", input); 16 return input; 17 /* POST */ 18 } else if (strcmp(req_method, "POST") == 0) { 19 length = atoi(getenv("CONTENT_LENGTH")); 20 /* CONTENT_LENGTH保存POST方法数据的长度 */ 21 printf("length:%d\n", length); 22 input = malloc(sizeof(char)*length + 1); 23 /* 从标准输入读取数据 */ 24 int i = 0; 25 while (i < length) { 26 input[i] = getc(fp); 27 i++; 28 } 29 input[i] = '\0'; 30 printf("<p>input : %s</p>", input); 31 return input; 32 } 33 return NULL; 34 } 35 36 int main(int argc, char *argv[]) 37 { 38 char *input; 39 char *req_method; 40 41 /* 确定发给服务器数据的类型,需要有一个空行, 42 * 将文本内容空开*/ 43 printf("Content-type:text/html\n\n"); 44 /* 从环境变量获取发送过来数据的方法 */ 45 req_method = getenv("REQUEST_METHOD"); 46 printf("<p>req_method:%s</p>", req_method); 47 48 input = getcgidata(stdin, req_method); 49 50 free(input); 51 52 return 0; 53 }
我是在虚拟机中安装ubuntu,并配置apache服务器,在终端编译(注意生成的cgi文件的权限,其他具有可执行权限),并移动到apache服务器的cgi目录/var/www/cgi-bin。将button.html文件移动到/var/www。
gcc button.c –o button.cgi sudo mv button.cgi /var/www/cgi-bin/ cp button.html /var/www/
3、结果分析
在windows上的浏览器搜索栏中输入“服务器的ip地址/buuton.html”,访问虚拟机中ubuntu上运行的apache服务器。例如我的服务器地址是192.168.1.112,在搜索栏中输入“192.168.1.112/button.html”。当然也可以直接在本地打开button.html文件,就不需要那么麻烦。如下图所示:
点击其中的某个按键,例如down。在搜索栏中可以看到,get的数据是在发送的信息头中,并且是在“?”之后。
使用Colasoft Capsa 7 Enterprise进行抓包,读取HTTP部分的信息。如下图所示,这就是发送给服务器的信息的信息头。
而将html中的method改正post之后,结果又会怎样呢?
点击down,结果如下:
可以看出,POST的数据是放在发送给服务器的数据信息体的内部的。抓包也可以看出。
4、例子
网页user.html
1 <html> 2 <form action="http://192.168.1.112/cgi-bin/user.cgi" method="POST"> 3 <table> 4 <tr> 5 <td>name</td> 6 <td><input name="name" size="8" /></td> 7 </tr> 8 <tr> 9 <td>country</td> 10 <td><input name="country" size="8" /></td> 11 </tr> 12 <tr> 13 <td>sex</td> 14 <td><input name="sex" size="8" /></td> 15 </tr> 16 <tr> 17 <td>age</td> 18 <td><input name="age" size="8" /></td> 19 </tr> 20 <tr> 21 <td>submit</td> 22 <td><input type="submit" value="submit" size="8"></td> 23 </tr> 24 </table> 25 </form> 26 </html>
程序user.c
1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <string.h> 4 5 typedef struct user_info { 6 char name[20]; 7 char country[20]; 8 char sex[10]; 9 int age; 10 } USER; 11 12 char *get_data(FILE *fp, char *req_method); 13 int parse_data(char *input, USER *user); 14 15 int main(int argc, char *argv[]) 16 { 17 int length; 18 char *input; 19 char *req_method; 20 USER user; 21 22 printf("content-type: text/html\n\n"); 23 24 printf("<title>user information</title>"); 25 printf("<h4>user info</h4>"); 26 req_method = getenv("REQUEST_METHOD"); 27 input = get_data(stdin, req_method); 28 /* 将获取的数据打印到浏览器中进行验证 */ 29 printf("<p>data:%s</p>", input); 30 parse_data(input, &user); 31 32 /* 解析后的数据打印到浏览器中 */ 33 printf("<p>name:%s</p>", user.name); 34 printf("<p>country:%s</p>", user.country); 35 printf("<p>sex:%s</p>", user.sex); 36 printf("<p>age:%d</p>", user.age); 37 38 free(input); 39 40 return 0; 41 } 42 /* 获取数据 */ 43 char *get_data(FILE *fp, char *req_method) 44 { 45 char *input; 46 int length; 47 48 if (strcmp(req_method, "GET") == 0) { 49 input = getenv("QUERY_STRING"); 50 return input; 51 } else if (strcmp(req_method, "POST") == 0) { 52 length = atoi(getenv("CONTENT_LENGTH")); 53 printf("length:%d\n", length); 54 input = malloc(sizeof(char)*length + 1); 55 int i = 0; 56 while (i < length) { 57 input[i] = getc(fp); 58 i++; 59 } 60 input[i] = '\0'; 61 return input; 62 } 63 return NULL; 64 } 65 66 /* 解析数据 */ 67 int parse_data(char *input, USER *user) 68 { 69 char *str; 70 char *data; 71 72 /* 分割数据的数据,strtok函数会将制定的分隔符"&"转化为'\0' 73 * 并返回分割出的字符串的首地址,str指向 "name=tony */ 74 str = strtok(input, "&"); 75 /* 指针偏移到'='后面,获取有用的数据 */ 76 data = strchr(str, '=') + 1; 77 /* 保存数据 */ 78 sprintf(user->name,"%s",data); 79 80 /* str指向country=China */ 81 str = strtok(NULL, "&"); 82 data = strchr(str, '=') + 1; 83 sprintf(user->country,"%s",data); 84 85 /* str指向sex=male */ 86 str = strtok(NULL, "&"); 87 data = strchr(str, '=') + 1; 88 sprintf(user->sex,"%s",data); 89 90 /* str指向age=23 */ 91 str = strtok(NULL, "&"); 92 data = strchr(str, '=') + 1; 93 user->age = atoi(data); 94 95 return 0; 96 }
user.html放在/var/www/,cgi放到/var/www/cgi-bin
sudo cp user.html /var/www gcc user.c -o user.cgi sudo cp user.cgi /var/www/cgi-bin
浏览器输入:
点击submit,发送数据,抓包,可以知道post的数据信息,发送的数据保存在信息体中。
查看colasoft下面的数据帧,也是同样的结果。
浏览器输出结果