在CGI的定义中,对于POST类型的表单,其内容被送到CGI程序的标准输入(在C语言中是stdin),而被传送的长度被放在环境变量CONTENT_LENGTH中。因而我们要做的就是,在标准输入中读入CONTENT_LENGTH长度的字符串。从标准输出读入数据听起来似乎要比从 环境变量中读数据来的要容易一些,其实则不然,有一些细节地方要注意,这在下面的程序中可以看到。特别要注意的一点就是:CGI程序和一般的程序有所不 同,一般的程序在读完了一个文件流的内容之后,会得到一个EOF的标志。但在CGI程序的表单处理过程中,EOF是永远不会出现的,所以千万不要读多于 CONTENT_LENGTH长度的字符,否这会有什么后果,谁也不知道(CGI规范中没有定义,一般根据服务器不同而有不同得处理方法)。

我们来看看到底如何从POST表单收集数据到CGI程序,下面给出了一个比较简单的C源代码:

/*
**post提交表单脚本
*/
#include < stdio.h >
#include < stdlib.h >
#include < string.h >#define EXTRA 5
/* 4个字节留给字段的名字"data", 1个字节留给"=" */ #define DATAFILE "data.txt"
/* 要被添加数据的文件 */ char *unencode(char *dest_str)
{register int x = 0, y = 0;char *temp_str = NULL; int ascii_one,ascii_two;temp_str = (char *)malloc(strlen(dest_str) * sizeof(char) +1);while(dest_str[y]){if(dest_str[y] == '+')//处理空格{temp_str[x] = ' ';}elseif(dest_str[y] == '%'){ if(dest_str[y+1] >= 'A')//将小写转为大写ascii_one = ((dest_str[y+1] & 0xdf) - 'A') + 10;else ascii_one = dest_str[y+1] - '0'; if(dest_str[y+2] >= 'A') ascii_two = ((dest_str[y+2] & 0xdf) - 'A') + 10;else ascii_two = dest_str[y+2] -'0';temp_str[x] = ascii_one * 16 + ascii_two; y += 2; }elsetemp_str[x] = dest_str[y];x++;y++; } temp_str[x] = '\0'; return (temp_str);} int main(void)
{ char *lenstr; char *data,*input; long len; printf("Content-Type:text/html\n\n");printf("<html><head>");printf("<title>Response</title>");printf("</head><body>");lenstr = getenv("CONTENT_LENGTH"); if(lenstr == NULL || sscanf(lenstr,"%ld",&len)!=1 ) printf("<P>表单提交错误"); else { FILE *f; input = (char*)malloc( sizeof(char) * len + 1);fgets(input, len+1, stdin); data = unencode(input+EXTRA);f = fopen(DATAFILE, "a");if(f == NULL) printf("<P>对不起,意外错误,不能够保存你的数据 "); else fputs(data, f); fclose(f); printf("<P>非常感谢,您的数据已经被保存<BR>%s",data);free(input);free(data);}printf("</body></html>");return 0;
} 

从本质上来看,程序先从CONTENT_LENGTH环境变量中得到数据的字长,然后读取相应长度的字符串。因为数据内容在传输的过程中是经过了编码的,所以必须进行相应的解码。编码的规则很简单,主要的有这几条:

1. 表单中每个每个字段用字段名后跟等号,再接上上这个字段的值来表示,每个字段之间的内容用&连结; 
2. 所有的空格符号用加号代替,所以在编码码段中出现空格是非法的; 
3. 特殊的字符比如标点符号,和一些有特定意义的字符如“+”,用百分号后跟其对应的ACSII码值来表示。

例如:如果用户输入的是: 
Hello there! 
那么数据传送到服务器的时候经过编码,就变成了data=Hello+there%21 上面的unencode()函数就是用来把编码后的数据进行解码的。在解码完成后,数据被添加到data.txt文件的尾部,并在浏览其中回显出来。 
下面给出了其相应的表单:

< form ACTION="/cgi-bin/collect.cgi" METHOD="POST" > 
< P >请输入您的留言(最多80个字符):< BR >< INPUT NAME="data" SIZE="60" MAXLENGTH="80" >< BR > 
< INPUT TYPE="SUBMIT" values="确定" > 
< /form >

事实上,这个程序只能作为例子,是不能够正式的使用的。它漏掉了很关键的一个问题:当有多个用户同时像文件写入数据是,肯定会有错误发生。而对于一个这样 的程序而言,文件被同时写入的几率是很大的。因此,在比较正式的留言版程序中,都需要做一些更多的考虑,比如加入一个信号量,或者是借助于一个钥匙文件 等。因为那只是编程的技巧问题,在这儿就不多说了。

HTTP服务器的实现--CGI中POST表单。相关推荐

  1. [RFC1867] HTML中基于表单的文件上传

    网络工作组:E. Nebel 征求意见:1867 L. Masinter 类别:试验 施乐公司 十一月 1995 HTML中基于表单的文件上传 这个备忘录的状态 这个备忘录为互联网社区定义了一个试验协 ...

  2. MOSS2007中实现表单验证

    MOSS2007中实现表单验证 转自阿喜的Spaces Microsoft Office SharePoint Server 2007 Forms Authentication 本文将演示如何在MOS ...

  3. form表单、控制器中接收表单提交数据的4种方式

    Form表单 这篇文章主要讲的是form表单的提交 之前我们接触过的form表单元素是在Bootstrap框架里面,这次也将用到Bootstrap框架去布局(见图表1)通过Bootstrap框架布局呈 ...

  4. extjs 提交表单给php,JavaScript_Extjs学习笔记之二 初识Extjs之Form,Extjs中的表单组件是Ext.form.Basic - phpStudy...

    Extjs学习笔记之二 初识Extjs之Form Extjs中的表单组件是Ext.form.BasicForm,不过最简单最常用的是Ext.form.FormPanel控件,它继承自Panel,具有一 ...

  5. html中form表单标签的使用

    在html中,表单是经常用到的,用来与用户交互并提交数据.今天要介绍的就是表单标签form标签 "form"作为英文单词有"表格"的意思 1.定义和用法 标签是 ...

  6. html5如何提交到邮箱,如何在html网页中提交表单直接发送到邮箱

    如何在html网页中提交表单直接发送到邮箱?此问题一直困扰了我很久很久,后来了解到jmail组件可以解决此问题,而且现在的付费空间基本都会有此组件.分别建立表单页和asp页面,提交表单后通过asp页面 ...

  7. JavaScript中的表单编程

    表单编程 1获取表单相关信息 1.什么是表单元素 1.什么是表单元素 在H TML中表单就是指form标签,它的作用是将用户输入或选择的数据提交给指定的服务器 2.如何获取表单元素 <form ...

  8. html语言中表格由什么组成,HTML中一个表单由什么组成

    在HTML中,一个完整的表单通常由表单元素(也称为表单控件).提示信息和表单域3个部分构成.表单元素包含了具体的表单功能项,如单行文本输入框.密码输入框.复选框.提交按钮.重置按钮等:表单域相当于一个 ...

  9. extjs中bind_Extjs中常用表单介绍与应用

    目标: 知道表单面板如何创建 了解表单面板中xtype的类型的应用 知道表单面板如何验证,绑定,取值 综合应用表单面板(玩转它) 内容: 首先我们要理解的是FormPanel也是继承panel组件的. ...

最新文章

  1. 前端验证码后端返回一个图片_Web后端开发(6)——简易图片验证码的制作
  2. docker redis 配置文件_基于Docker搭建Redis一主两从三哨兵
  3. mysql更改数据语句6_MySQL的SQL语句 - 数据定义语句(6)- ALTER TABLE 语句(1)
  4. 一段最简单的使用socket.io进行服务器和客户端通信的例子代码
  5. java 泰勒级数_鸡群优化算法(CSO)、蜻蜓算法(DA)、乌鸦搜索算法(CSA)、泰勒级数(Taylor series)...
  6. 服务器电脑 默认虚拟内存,服务器是否需要设置虚拟内存
  7. 彻底明白Java的IO系统
  8. android4.0 禁止横竖屏切换使用 android:configChanges=orientation|keyboardHidden无效
  9. 项目延期的4大原因及解决方案!
  10. 计算机病毒实验教程pdf,计算机病毒实验报告-1
  11. 向日葵公主与驴的爱情故事
  12. 高并发场景以及应对技巧
  13. 《熟练掌握OpenCV----实用计算机视觉工程案例》第5章 车牌号码识别
  14. Power BI产品帕累托分析
  15. LTE中RB、RBG、CCE、REG
  16. python实现批量翻译
  17. html5秘籍当当,酱料制作秘籍
  18. ImportError: cannot import name ‘XXXXX‘ from ‘XX‘解决方案
  19. markdown设置锚点
  20. 完美Crack:Froala Editor 4.0.16 Patch

热门文章

  1. Oracle数据库wm_concat()函数的使用方法
  2. COCO数据集的介绍和使用
  3. 微信公众号一键拨号功能
  4. 戴眼镜会需要眼镜盒,该怎么创建眼镜盒嗯?下面我们就来看看3dmax创建眼镜盒模型的技巧。
  5. 剑指Offer——联通研究院笔、面试题 (Offer-1已收割)
  6. Python函数:np.sum()以及axis=0、axis=1用法
  7. [51nod1074]约瑟夫环V2
  8. 骨传导耳机是怎么传声的、骨传导耳机的优点是什么
  9. 中国碎石设备市场趋势报告、技术动态创新及市场预测
  10. tabBar的简单使用,以及扩展