用c语言写cgi程序(3)---实现文件上传
敬告:其实当前的cgic版本已经有上传的功能了,可以看看自带的test文件用C语言编写cgi程序的话,多半会用到CGIC。
这是个非常流行的库,遇到文件上传之类的应用更是离不开它。
官方页面及下载地址为:/cgic/#obtain不少网站都有文件上传的功能,本文展示如何用CGIC库编写文件上传的服务端程序,最后给出一段简单的HTML代码,供大家测试使用。
下载: upload.c[cpp:nogutter]view plaincopyprint?#include<stdio.h>#include<string.h>#include<unistd.h>#include<fcntl.h>#include<sys/stat.h>#include"cgic.h"#define BufferLen 1024int cgiMain(void){cgiFilePtr file;int targetFile;mode_t mode;char name[128];char fileNameOnServer[64];char contentType[1024];char buffer[BufferLen];char *tmpStr=NULL;int size;int got,t;cgiHeaderContentType("text/html");//取得html页面中file元素的值,应该是文件在客户机上的路径名if (cgiFormFileName("file", name, sizeof(name)) !=cgiFormSuccess) {fprintf(stderr,"could not retrieve filename/n");goto FAIL;}cgiFormFileSize("file", &size);//取得文件类型,不过本例中并未使用cgiFormFileContentType("file", contentType, sizeof(contentType));//目前文件存在于系统临时文件夹中,通常为/tmp,通过该命令打开临时文件。
临时文件的名字与用户文件的名字不同,所以不能通过路径/tmp/userfilename的方式获得文件if (cgiFormFileOpen("file", &file) != cgiFormSuccess) {fprintf(stderr,"could not open the file/n");goto FAIL;}t=-1;//从路径名解析出用户文件名while(1){tmpStr=strstr(name+t+1,"//");if(NULL==tmpStr)tmpStr=strstr(name+t+1,"/");//if "//" is not path separator, try "/"if(NULL!=tmpStr)t=(int)(tmpStr-name);elsebreak;}strcpy(fileNameOnServer,name+t+1);mode=S_IRWXU|S_IRGRP|S_IROTH;//在当前目录下建立新的文件,第一个参数实际上是路径名,此处的含义是在cgi程序所在的目录(当前目录))建立新文件targetFile=open(fileNameOnServer,O_RDWR|O_CREAT|O_TRUNC|O_APPEND,mode); if(targetFile<0){fprintf(stderr,"could not create the new file,%s/n",fileNameOnServer);goto FAIL;}//从系统临时文件中读出文件内容,并放到刚创建的目标文件中while (cgiFormFileRead(file, buffer, BufferLen, &got) ==cgiFormSuccess){if(got>0)write(targetFile,buffer,got);}cgiFormFileClose(file);close(targetFile);goto END;FAIL:fprintf(stderr,"Failed to upload");return 1;END:printf("File /"%s/" has been uploaded",fileNameOnServer);return 0;}假设该文件存储为upload.c,则使用如下命令编辑:gcc -Wall upload.c cgic.c -o upload.cgi编译完成后把upload.cgi复制到你部署cgi程序的目录(通常命名为cgi-bin)。
正式部署时,请务必修改用open创建新文件那一行代码。
把open的第一个参数设置为目标文件在服务器上存储的绝对路径,或者相对于cgi程序的相对路径。
本例中,出于简单考虑,在cgi程序所在目录下创建新文件。
测试用HTML代码:下载: upload.html<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN""/TR/html4/strict.dtd"><html><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8"><title>Test Upload</title><meta name="author" content="Jack"><!-- Date: 2007-08-30 --></head><body><form action="cgi-bin/upload.cgi" method="post" enctype="multipart/form-data" target ="_blank"><input type="file" name="file" value="" /><input type="submit" name="submit" value="OK"></form></body></html>最后的文件目录结构为/MyWebRoot|—/upload.html|—/cgi-bin|——/upload.cgi当然,你必须配置能够cgi-bin,并且程序要有权限在cgi-bin目录下创建文件(因为此例把文件上传到cgi-bin目录下)。
那么如何控制上传文件的大小呢?因为你有时会不允许用户上传太大的文件。
通过分析cgic.c的源代码,我们发现它定义了一个变量cgiContentLength,表示请求的长度。
但我们需要首先判断这是一个上传文件的请求,然后才能根据cgiContentLength来检查用户是否要上传一个太大的文件。
cgic.c的main函数中进行了一系列if-else判断来检查请求的类型,首先确定这是一个post 请求,然后确定数据的编码方式为“multipart/form-data”,这个判断通过之后,就要开始准备接收数据了。
所以我们要在接收数据开始之前使用cgiContentLength判断大小,如果超过标准,就立即返回,不允许继续操作。
下面贴出修改后代码片段(直接修改cgic.c的源代码即可):[cpp:nogutter]view plaincopyprint?else if (cgiStrEqNc(cgiContentType, "multipart/form-data")) {#ifdef CGICDEBUGCGICDEBUGSTARTfprintf(dout, "Calling PostMultipartInput/n");CGICDEBUGEND#endif /* CGICDEBUG *///我的代码//UpSize:文件长度上限值,以byte为单位,UpSize是一个int变量,因为cgiContentLength 的类型为intif(cgiContentLength>UpSize){cgiHeaderContentType("text/html");printf("File too large!/n");cgiFreeResources();return -1;}//我的代码结束if (cgiParsePostMultipartInput() != cgiParseSuccess) {#ifdef CGICDEBUGCGICDEBUGSTARTfprintf(dout, "PostMultipartInput failed/n"); CGICDEBUGEND#endif /* CGICDEBUG */ cgiFreeResources();return -1;}#ifdef CGICDEBUG CGICDEBUGSTARTfprintf(dout, "PostMultipartInput succeeded/n"); CGICDEBUGEND#endif /* CGICDEBUG */}}。
cgi教程:第七章
本文由feixue2588贡献
doc文档可能在WAP端浏览体验不佳。建议您优先选择TXT,或下载源文件到本机查看。
第七章: 要手段。一般来说,考虑到 CGI 程序的安全和一些敏感问题,服务器是不会 轻易开放文件上传权利的。 今天的程序是由 WEBSITE1.1 附带的一个 upload.exe 程序, VB 编写而成。 由 所以我要讲的也就是 VB 写 WIN-CGI 时候的一些问题。 VB 写 Win-CGI: 在 Windows 环境下,WEB 服务器和一个 Windows CGI 之间是通过临时文件来传送数据的。这个过程如下: 1.Web 服务器接受一个客户机对 Windows CGI 程序的请求,这个请求也称为 Windows CGI 请求。 2.Web 服务器把要传送给 Windows CGI 程序的数据放在一个叫 CGI profile 的主输入文件。在某些情况下,还会增 加一个文件。 3.Web 服务器执行 CGI 程序,把 CGI profile 作为它的第一个参数。 4.Windows CGI 开始执行,服务器等待 Windows CGI 进程结束。在等待过程中,服务器还可以处理其他请求,比 如另一个新的 CGI 进程或 HTTP 请求。 5.Windows CGI 程序读取作为命令行参数的 profile 文件并完成必要的处理,CGI 程序也许要使用 porfile 文件中的 数据和其他相关的辅助文件中的数据。 6.在 Windows CGI 程序结束前,把它的应答写在 profile 文件指定的输出文件中。 7.得到 CGI 程序处理结果后,WEB 服务器读取输出文件,看看输出数据是否要打包,并把最后数据发给客户机。 8.WEB 服务器随后就删除处理这个请求时产生的临时文件。如果在服务器管理器注册时,不删除临时文件,则保 留这些临时文件。 总的说,基于文件的传输过程是比较古老的。但它是最常用的通讯方式。 CGI32.BAS CGI32.BAS 是给 windows 系列的使用者在 VB4.0 或更高的环境下开发 Windows-cgi 而写的一个程序接口。本文假 设你已经对 VB 编程非常熟悉,所以对于使用 VB 的过程我就省略不说了。在写 Win-CGI 程序的时候,请将 VB 环境 中的有效对象全部关掉(Custom controls) ,并将 CGI32.bas 加入 project 中。随后创建一个子程序 CGI_Main() Sub CGI-Main() 'Win-CGI 程序内容 end sub 对于 CGI32.bas,如果你还没有,请在这里下载。 Sub Main() On Error GoTo ErrorHandler If Trim$(Command$) = "" Then ' Interactive start Inter_Main ' Call interactive main Exit Sub ' Exit the program End If InitializeCGI ' Create the CGI environment '=========== CGI_Main ' Execute the actual "script" '=========== Cleanup: Close #CGI_OutputFN Exit Sub ' End the program
c语言开发cgi基础
printf ("Content-type:text/plain\n\n"); n=0; if (getenv("CONTENT-LENGTH")) n=atoi(getenv("CONTENT-LENGTH")); for (i=0; i<n;i++){ int is-eq=0; c=getchar(); switch (c){ case '&':c='n';break; case '+':c=' ';break; case '%':{ char s[3]; s[0]=getchar(); s[1]=getchar(); s[2]=0; c=htoi(s); i+=2;
Page 17
Page 18
数据传送格式
当用户填完表格并按了SUBMIT按钮后,Web浏览器并非 将用户所填的数据直接送给Web服务器,而先要经过一定 的编码处理。Web浏览器总是将数据按照“变量名=变量 值”这样的数据对格式进行编码,并且每对数据之间用一 个&符号相连接。其中“变量名”就是Form元素中的 NAME属性值;“变量值”则是用户在输入框中所输入的 数据,或者是用户所选择的数据(即RADIO, CHECKBOX,OPTION中的VALUE值)。并且Web浏览 器将用户数据中的所有空格都替换成 "+ "号。另外一些特 殊字符的表示使用转义符 "% "后面加上该特殊字符的十 六进制ASCII码。特殊字符主要包括 "= "、 "+ "、 "& "、 "% "以及多行文本中的回车,换行符,所有不能直接显示 的高位ASCII符等。
用c语言写cgi程序
用c语言写cgi程序(1)代码用这个:/question/28759329.html再贴一下:view plaincopy to clipboardprint?1. #include <stdio.h>2. #include <stdlib.h>3. i nt main(void)4. {5. c har *data;6. l ong m,n;7. p rintf("%s%c%c ","Content-Type:text/html;charset=gb2312",13,10);8. p rintf("<TITLE>乘法结果< /TITLE > ");9. p rintf("<H3>乘法结果< /H3 > ");10. data = getenv("QUERY_STRING");11. if(data == NULL)12. printf("<P>错误!数据没有被输入或者数据传输有问题");13. else if(sscanf(data,"m=%ld&n=%ld",&m,&n)!=2)14. printf("<P>错误!输入数据非法。
表单中输入的必须是数字。
");15. else16. printf("<P>%ld和%ld的成绩是:%ld。
",m,n,m*n);17. return 0;18. }19. 编译运行出.exe的文件。
是否要把后缀名改为.cgi?20. 此程序的表单如下:21. <FORM ACTION="/cgi-bin/mult.cgi">22. <P>请在下面填入乘数和被乘数,按下确定后可以看到结果。
CGIC简明教程目录(CGI篇)
CGIC简明教程目录(CGI篇)CGIC简明教程目录本系列的目的是演示如何使用C语言的CGI库“CGIC”完成Web开发的各种要求。
基础知识* 1: 使用CGIC的基本思路* 2: 获取Get请求字符串* 3: 反转义* 4: 获取请求中的参数值进阶训练* 用CGIC实现文件上传CGIC简明教程1:使用CGIC的基本思路C语言编程是一项复杂且容易出错的工作,所以在完成复杂任务时,一定要选择合适的库。
对于用C语言编写CGI程序则更是如此。
CGIC是非常优秀的C语言CGI库函数。
其下载地址为:/cgic/#obtain,现在的版本号是2.05。
本站从今天开始,将逐步介绍如何使用CGIC完成各种操作,也可以说是一个Tutorial。
(注:本系列涉及的编程环境都是Linux,Windows用户需要对用到的操作系统命令稍作修改)本文纲要:CGIC的安装、测试安装、使用CGIC的基本思路;1) CGIC的下载安装从上面提供的官方网址下载了CGIC库之后,解开压缩包,里面有大约10个文件,有用的是:cgic.h:头文件;cgic.c:CGIC的源代码文件;cgictest.c:CGIC库的作者提供的一个CGI程序例子;capture.c:用于调试CGI程序的工具;Makefile:安装CGIC的脚本文件;可以看到,整个库实际上就是cgic.c一个文件,可以说是非常的精炼。
我们可以把CGIC安装为操作系统的一个动态链接库,这样我们每次编译的时候,就不需要有cgic.c这个源文件了。
但是由于需要(以后将会看到),我们将修改cgic.c代码,所以我们不把它安装进系统。
每次编译的时候,只要把cgic.c和cgic.h放到当前文件夹就好了。
2) 测试安装在开始编写你自己的CGI程序之前,一定要先走通他的例子程序,免得后来程序出错的时候还不知道是配置有问题,还是你的程序代码有问题。
我们用他自带cgictest.c来实现自己的第一个C语言CGI程序。
c#文件上传源代码
c#⽂件上传源代码⽂件上传这⾥分上传到服务器的⽂件夹和数据库1:上传到⽂件夹⾸先看aspx页⾯:程序代码:<tr bgcolor="#ffffff"><td height="24"><input type="file" id="Up_file" class="edline" runat="server" style="WIDTH: 456px; HEIGHT: 20px" size="60" name="Up_file"></td></tr><TR bgcolor="#ffffff"><TD height="24" align="center"><asp:Button ID="submit" Runat="server" Text="⽂件上传" CssClass="Cmdbut" Height="20px"></asp:Button></TD></TR>下⾯是后台,及"⽂件上传"按钮触发的事件:程序代码:private void submit_Click(object sender, System.EventArgs e){HttpPostedFile postedFile = this.Up_file.PostedFile; //得到要上传⽂件string fileName, fileExtension;fileName = System.IO.Path.GetFileName(postedFile.FileName); //⽂件名称if (fileName != ""){fileExtension = System.IO.Path.GetExtension(fileName); //上传⽂件的扩展名string new_filename = fileExtension; //给⽂件重新命名//postedFile.FileName:客户端⽂件地址//postedFile.ContentType.ToString():上传的⽂件类型//保存⽂件到⽂件夹,地址是当前页⾯的同⼀级⽬录下的files⽂件夹中postedFile.SaveAs(System.Web.HttpContext.Current.Request.MapPath("files/") + new_filename);//.....可以把⽂件的相应信息保存到数据库中去。
cgi语言_CGI之C语言篇
cgi语言:CGI之C语言篇疯狂代码 / ĵ:http://CDevelopment/Article14437.html为什么要进行CGI编程? 在HTML中当客户填写了表单并按下了发送(submit)按钮后表单内容被发送到了服务器端般这时就需要有个服务器端脚本来对表单内容进行些处理或者是把它们保存起来或者是按内容进行些查询或者是些别什么没有了CGIWEB世界就完全失去了它交互性所有信息都变成单向了而不能够有任何反馈 有人认为可以用javascript来代替CGI这其实是个概念上javascript只能够在客户浏览器中运行而CGI却是工作在服务器上他们所做工作有些交集比如表单数据验证类但是javascript是绝对无法取代CGI但可以这样说如果项工作即能够用javascript来做又可以用CGI来做那么绝对要使用javascript在执行速度上javascript比CGI有着先天优势只有那些在客户端解决不了问题比如和某个远程数据库交互这时就应该使用CGI了 简单说来CGI是用来沟通HTML表单和服务器端接口(erface)说它是接口也就是说CGI并不是种语言而是可以被其他语言所应用个规范标准集理论上讲你可以用任何语言来编写CGI只要在编程时候符合CGI规范标准所定义些东西就可以了由于C语言在平台无关性上表现不错(几乎在任何系统平台下都有其相应编译器)而且对大多数员而言都算得上很熟悉(不像Perl)因此C是CGI编程首选语言的这儿我们介绍就是如何使用C来编写CGI 作为CGI编程最为简单例子就是进行表单处理因而在这篇文章中我们主要介绍就是如何用C来编写CGI来进行表但处理 GET表单处理 对于那些使用了属性“METHOD=GET”表单(或者没有METHOD属性这时候GET是其缺省值)CGI定义为:当表单被发送到服务器断后表单中数据被保存在服务器上个叫做QUERY_STRING环境变量中这种表单处理相对简单只要读取环境变量就可以了这点对区别语言有区别做法在C语言中你可以用库getenv(定义在标准库stdlib中)来把环境变量值作为个串来存取你可以在取得了串中数据后运用些小窍门技巧进行类型转换这都是比较简单了在CGI中标准输出(output)(比如在C中stdout文件流)也是经过重定义了它并没有在服务器上产生任何输出内容而是被重定向到客户浏览器这样如果编写个CCGI时候把个HTML文档输出到它stdout上这个HTML文档会被在客户端浏览器中显示出来这也是CGI个基本原理 我们来看看具体实现下面是段HTML表单:<formACTION="/cgi-bin/mult.cgi"><P>请在下面填入乘数和被乘数按下确定后可以看到结果<INPUTNAME="m"SIZE="5"><INPUTNAME="n"SIZE="5"><BR><INPUTTYPE="SUBMIT"values="确定"></form> 我们要实现功能很简单就是把表单中输入数值乘起来然后输出结果其实这个功能完全可以用javascript来实现但为了让尽量简单易懂我还是选择了这个小小乘法来作为举例 下面就是处理这个表单CGI对应于form标签中ACTION属性值#<stdio.h>#<stdlib.h>(void){char*data;longm,n;prf("%s%c%c","Content-Type:text/html;char=gb2312",13,10);prf("<TITLE>乘法结果</TITLE>");prf("<H3>乘法结果</H3>");data=getenv("QUERY_STRING");(dataNULL)prf("<P>!数据没有被输入或者数据传输有问题");(sscanf(data,"m=%ld&n=%ld",&m,&n)!=2)prf("<P>!输入数据非法表单中输入必须是数字");prf("<P>%ld和%ld成绩是:%ld",m,n,m*n);0;} 具体C语法就不多讲了我们来看看它作为CGI所特殊地方 前面已经提到标准输出内容就是要被显示在浏览器中内容第行输出内容是必须也是个CGI所特有:prf("%s%c%c","Content-Type:text/html",13,10)这个输出是作为HTML文件头CGI不仅可以像浏览器输出HTML文本而且可以输出图像声音的类东西这行告诉浏览器如何处理接受到内容在Content-Type定义后面跟有两行空行这也是不可缺少所有CGI头部输出都是相近因而可以为其定义个来节省编程时间这是CGI编程常用个窍门技巧 在后面了用了库getevn来得到QUERY_STRING内容然后使用sscanf把每个参数值取出来要注意是sscanf使用方法其他就没有什么了和般C没有区别 把编译后改名为mult.cgi放在/cgi-bin/目录下面就可以被表单了这样个处理GET方式表单CGI就大功告成了 POST表单处理 下面我们来考虑另外种表单传送思路方法:POST假设我们要实现任务是这样:把表单中客户输入段文本内容添加到服务器上个文本文件后面这可以看作是个留言版雏形显然这个工作是无法用javascript这种客户端脚本来实现也算得上真正意义上CGI了 看起来这个问题和上面讲内容很相近仅仅是用区别表单和区别脚本()而已但实际上这中间是有些区别在上面例子中GET处理思路方法可以看作是“纯查询(purequery)”类型也就是说它和状态无关同样数据可以被提交任意次数而不会引起任何问题(除了服务器些小小开销)但是现在任务就区别了至少它要改变个文件内容因而可以说它是和状态有关这也算是POST和GET区别的而且GET对于表单长度是有限制而POST则不然这也是在这个任务中选用POST思路方法主要原因但相对对GET处理速度就要比POST快些 在CGI定义中对于POST类型表单其内容被送到CGI标准输入(在C语言中是stdin)而被传送长度被放在环境变量CONTENT_LENGTH中因而我们要做就是在标准输入中读入CONTENT_LENGTH长度串从标准输出读入数据听起来似乎要比从环境变量中读数据来要容易些其实则不然,有些细节地方要注意这在下面中可以看到特别要注意点就是:CGI和般有所区别般在读完了个文件流内容的后会得到个EOF标志但在CGI表单处理过程中EOF是永远不会出现所以千万不要读多于CONTENT_LENGTH长度否这会有什么后果谁也不知道(CGI规范标准中没有定义般根据服务器区别而有区别得处理思路方法) 我们来看看到底如何从POST表单收集数据到CGI下面給出了個比较简单C源代碼:#<stdio.h>#<stdlib.h>#MAXLEN80#EXTRA5/*4个字节留给字段名字"data",1个字节留给"="*/ #MAXINPUTMAXLEN+EXTRA+2/*1个字节留给换行符还有个留给后面NULL*/#DATAFILE"../data/data.txt"/*要被添加数据文件*/voidunencode(char*src,char*last,char*dest) {for(;src!=last;src,dest)(*src"+")*dest="";(*src"%"){code;(sscanf(src+1,"%2x",&code)!=1)code="?";*dest=code;src2;}*dest=*src;*dest="";*dest="";}(void){char*lenstr;charinput[MAXINPUT],data[MAXINPUT];longlen;prf("%s%c%c","Content-Type:text/html;char=gb2312",13,10);prf("<TITLE>Response</TITLE>");lenstr=getenv("CONTENT_LENGTH");(lenstrNULL||sscanf(lenstr,"%ld",&len)!=1||len>MAXLEN) prf("<P>表单提交");{FILE*f;fgets(input,len+1,stdin);unencode(input+EXTRA,input+len,data);f=fopen(DATAFILE,"a");(fNULL)prf("<P>对不起意外不能够保存你数据");fputs(data,f);fclose(f);prf("<P>非常感谢您数据已经被保存<BR>%s",data);}0;} 从本质上来看先从CONTENT_LENGTH环境变量中得到数据字长然后读取相应长度串数据内容在传输过程中是经过了编码所以必须进行相应解码编码规则很简单主要有这几条: 1.表单中每个每个字段用字段名后跟等号再接上上这个字段值来表示每个字段的间内容用&连结; 2.所有空格符号用加号代替所以在编码码段中出现空格是非法; 3.特殊比如标点符号和些有特定意义如“+”用百分号后跟其对应ACSII码值来表示 例如:如果用户输入是: Hellothere! 那么数据传送到服务器时候经过编码就变成了data=Hello+there%21上面unencode()就是用来把编码后数据进行解码在解码完成后数据被添加到data.txt文件尾部并在浏览其中回显出来 把文件编译完成后把它改名为collect.cgi后放在CGI目录中就可以被表单了下面给出了其相应表单:<formACTION="/cgi-bin/collect.cgi"METHOD="POST"><P>请输入您留言(最多80个):<BR><INPUTNAME="data"SIZE="60"MAXLENGTH="80"><BR><INPUTTYPE="SUBMIT"values="确定"></form> 事实上这个只能作为例子是不能够正式使用它漏掉了很关键个问题:当有多个用户同时像文件写入数据是肯定会有发生而对于个这样而言文件被同时写入几率是很大因此在比较正式留言版中都需要做些更多考虑比如加入个信号量或者是借助于个钥匙文件等那只是编程窍门技巧问题在这儿就不多说了 最后我们来写个浏览data.txt文件CGI这只需要把内容输出到stdout就可以了: #<stdio.h> #<stdlib.h> #DATAFILE"../data/data.txt" (void) { FILE*f=fopen(DATAFILE,"r"); ch; (fNULL){ prf("%s%c%c", "Content-Type:text/html;char=gb2312",13,10); prf("<TITLE></TITLE>"); prf("<P><EM>意外无法打开文件</EM>");} { prf("%s%c%c", "Content-Type:text/plain",13,10); while((ch=getc(f))!=EOF) putchar(ch); fclose(f);} 0; } 这个唯要注意是:它并没有把data.txt包装成HTML格式后再输出而是直接作为简单文本(plaext)输出这只要在输出头部用text/plain类型代替text/html就可以了浏览器会根据Content-Type类型自动选择相应处理思路方法 要触发这个也很简单没有数据要输入所以只需个按钮就可以搞定了: <formACTION="/cgi-bin/viewdata.cgi"> <P><INPUTTYPE="SUBMIT"values="察看"> </form> 到这儿些基本用C编写CGI原理就将完了当然就凭讲这些内容还很难编写出个好CGI这需要进步学习CGI规范标准定义以及些其他CGI编程特有窍门技巧 这篇文章目也就是要你了解下CGI编程概念事实上现在些主流服务器端脚本编程语言如ASPPHPJSP等都基本上具备了CGI编程大部分功能但他们在使用上确实是比无论用什么语言进行CGI编程都要容易多所以在进行服务器端编程时候般都会首先考虑使用这些脚本编程语言只有当他们也解决不了比如要进行些更为底层编程时候才会用到CGI 2009-2-12 5:06:00疯狂代码 /。
C语言菜鸟级文件传输
#include <stdio.h>
#include <winsock2.h>
#include <sys/stat.h>
#include <windows.h>
#pragma comment( lib, "WS2_32" )
void jindu(unsigned long i, unsigned long cont);
SOCKET FileSock,S; //声明套接字
struct sockaddr_in Local,Remote; // 配置socket相关信息(ip,port...)
char *ip,temp[2048];
int nLen = sizeof(SOCKADDR_IN);
FILE * fstream = NULL ;//文件指针
int flag = 1;
int nNumRead = 0;
unsigned long filesize = 0;
char ch_filesize[15];
memset(ch_filesize, 0, 15);
if (argc == 2) //当有文件路径参数 才打开文件
char temp[2048], ch_filesize[15];
int nNumRead = 0;
SOCKET FileSock;
struct sockaddr_in Remote;
FILE * fstream = NULL;
if (argc != 1)
{
fstream = fopen( argv[2], "wb" );
C语言Web开发使用CGI和服务器端脚本
C语言Web开发使用CGI和服务器端脚本Web开发是当今社会中一个非常热门的领域。
为了开发出高效、强大的网站和网络应用程序,掌握编程语言成为了必备技能之一。
而在Web开发中,C语言是一种强大而灵活的选择。
本文将介绍C语言在Web开发中使用CGI(通用网关接口)和服务器端脚本的方法和技巧。
一、CGI简介CGI是一种将网页与服务器端脚本语言(如C语言)进行交互的标准接口。
它允许我们在网页中执行服务器端的脚本,从而动态地生成和展示内容。
在C语言中,我们可以使用CGI来处理来自用户的请求,并生成相应的响应内容。
二、为什么选择C语言虽然现代Web开发中使用的语言有很多种,但是C语言在性能和灵活性方面具有独特的优势。
C语言是一种基础且底层的语言,可以直接操作内存和硬件资源,提供了更精确的控制和更高效的执行。
因此,对于一些对性能要求较高的Web应用程序,使用C语言进行开发是一种明智的选择。
三、CGI的实现步骤1. 编写C语言脚本首先,我们需要编写一个C语言脚本来实现我们的逻辑。
这个脚本将接收来自用户的请求,并根据请求生成相应的响应。
我们可以使用C标准库中的相关函数来处理网络通信和数据传输。
2. 配置服务器接下来,我们需要配置服务器以支持CGI脚本的执行。
具体的配置方法因服务器而异,一般需要修改服务器配置文件并将CGI脚本的位置和访问权限进行设置。
3. 发布脚本将编写好的C语言脚本发布到服务器上的指定目录中。
确保脚本的路径和访问权限设置正确,以便服务器能够正确地执行脚本。
四、服务器端脚本的使用除了使用CGI,我们还可以使用服务器端脚本来进一步简化和优化Web开发过程。
服务器端脚本是在服务器执行的脚本,用于生成和处理动态的Web内容。
在C语言中,我们可以使用FastCGI(一种高性能的CGI实现)等技术来开发服务器端脚本。
1. FastCGI简介FastCGI是一种高性能的CGI协议扩展,旨在提供更高效的CGI脚本执行方式。
用C语言编写CGI程序
用C语言编写CGI程序用C语言编写CGI程序一、CGI概述CGI(公用网关接口)规定了Web服务器调用其他可执行程序(CGI程序)的接口协议标准。
Web服务器通过调用CGI程序实现和Web浏览器的交互,也就是CGI程序接受Web浏览器发送给Web服务器的信息,进行处理, 将响应结果再回送给Web服务器及Web浏览器。
CGI 程序一般完成Web网页中表单(Form)数据的处理、数据库查询和实现与传统应用系统的集成等工作。
CGI程序可以用任何程序设计语言编写,如Shell脚本语言、Perl、Fortran、Pascal、C语言等。
但是用C语言编写的CGI程序具有执行速度快、安全性高(因为C语言程序是编译执行且不可被修改)等特点。
CGI接口标准包括标准输入、环境变量、标准输出三部分。
1.标准输入CGI程序像其他可执行程序一样,可通过标准输入(stdin)从Web服务器得到输入信息,如Form中的数据,这就是所谓的向CGI程序传递数据的POST方法。
这意味着在操作系统命令行状态可执行CGI程序,对CGI程序进行调试。
POST方法是常用的方法,本文将以此方法为例,分析CGI程序设计的方法、过程和技巧。
2.环境变量操作系统提供了许多环境变量,它们定义了程序的执行环境,应用程序可以存取它们。
Web 服务器和CGI接口又另外设置了自己的一些环境变量,用来向CGI 程序传递一些重要的参数。
CGI的GET方法还通过环境变量QUERY-STRING向CGI程序传递Form中的数据。
3.标准输出CGI程序通过标准输出(stdout)将输出信息传送给Web服务器。
传送给Web服务器的信息可以用各种格式,通常是以纯文本或者HTML文本的形式,这样我们就可以在命令行状态调试CGI程序,并且得到它们的输出。
下面是一个简单的CGI程序,它将HTML中Form的信息直接输出到We b浏览器。
引用#include < stdio.h >#include < stdib.h >main(){int,i,n;printf (〃Contenttype:text/plainnn〃);n=0;if(getenv(〃CONTENT-LENGTH〃))n=atoi(getenv(CONTENT-LENGTH〃));for (i=0;i putchar(getchar());putchar (′n′);fflush(stdout);}下面对此程序作一下简要的分析。
文件传输C语言实现
////////////////////////////////////#include <netinet/in.h> // for sockaddr_in#include <sys/types.h> // for socket#include <sys/socket.h> // for socket#include <stdio.h> // for printf#include <stdlib.h> // for exit#include <string.h> // for bzero#include <time.h> //for time_t and time#define HELLO_WORLD_SERVER_PORT 7754#define LENGTH_OF_LISTEN_QUEUE 20#define BUFFER_SIZE 1024int main(int argc, char **argv){struct sockaddr_in server_addr;bzero(&server_addr,sizeof(server_addr));server_addr.sin_family = AF_INET;server_addr.sin_addr.s_addr = htons(INADDR_ANY);server_addr.sin_port = htons(HELLO_WORLD_SERVER_PORT);// time_t now;FILE *stream;int server_socket = socket(AF_INET,SOCK_STREAM,0);if( server_socket < 0){printf("Create Socket Failed!");exit(1);}if( bind(server_socket,(struct sockaddr*)&server_addr,sizeof(server_addr))) {printf("Server Bind Port : %d Failed!", HELLO_WORLD_SERVER_PORT); exit(1);}if ( listen(server_socket, LENGTH_OF_LISTEN_QUEUE) ){printf("Server Listen Failed!");}while (1)struct sockaddr_in client_addr;socklen_t length = sizeof(client_addr);int new_server_socket = accept(server_socket,(struct sockaddr*)&client_addr,&length); if ( new_server_socket < 0){printf("Server Accept Failed!\n");break;}char buffer[BUFFER_SIZE];bzero(buffer, BUFFER_SIZE);strcpy(buffer,"Hello,World! ");strcat(buffer,"\n"); //send(new_server_socket,buffer,BUFFER_SIZE,0);bzero(buffer,BUFFER_SIZE);= recv(new_server_socket,buffer,BUFFER_SIZE,0);if (length < 0){printf("Server Recieve Data Failed!\n");exit(1);}printf("\n%s",buffer);if((stream = fopen("z.mp3","r"))==NULL){printf("The file 'data1' was not opened! \n");exit(1);}elseprintf("The file 'filename' was opened! \n");bzero(buffer,BUFFER_SIZE);int lengsize = 0;while((lengsize = fread(buffer,1,1024,stream)) > 0){printf("lengsize = %d\n",lengsize);if(send(new_server_socket,buffer,lengsize,0)<0){printf("Send File is Failed\n");break;}bzero(buffer, BUFFER_SIZE);}if(fclose(stream))printf("The file 'data' was not closed! \n");exit(1);close(new_server_socket);}close(server_socket);return 0;}//client.c////////////////////////////////////#include <netinet/in.h> // for sockaddr_in#include <sys/types.h> // for socket#include <sys/socket.h> // for socket#include <stdio.h> // for printf#include <stdlib.h> // for exit#include <string.h> // for bzero#include <time.h> //for time_t and time #include <arpa/inet.h>#define HELLO_WORLD_SERVER_PORT 7754#define BUFFER_SIZE 1024int main(int argc, char **argv){if (argc != 2){printf("Usage: ./%s ServerIPAddress\n",argv[0]);exit(1);}//time_t now;FILE *stream;struct sockaddr_in client_addr;bzero(&client_addr,sizeof(client_addr));client_addr.sin_family = AF_INET;client_addr.sin_addr.s_addr = htons(INADDR_ANY);client_addr.sin_port = htons(0);int client_socket = socket(AF_INET,SOCK_STREAM,0);if( client_socket < 0){printf("Create Socket Failed!\n");exit(1);}if( bind(client_socket,(struct sockaddr*)&client_addr,sizeof(client_addr))){printf("Client Bind Port Failed!\n");exit(1);}struct sockaddr_in server_addr;bzero(&server_addr,sizeof(server_addr));server_addr.sin_family = AF_INET;if(inet_aton(argv[1],&server_addr.sin_addr) == 0){printf("Server IP Address Error!\n");exit(1);}server_addr.sin_port = htons(HELLO_WORLD_SERVER_PORT);socklen_t server_addr_length = sizeof(server_addr);if(connect(client_socket,(struct sockaddr*)&server_addr, server_addr_length) < 0) {printf("Can Not Connect To %s!\n",argv[1]);exit(1);}char buffer[BUFFER_SIZE];bzero(buffer,BUFFER_SIZE);int length = recv(client_socket,buffer,BUFFER_SIZE,0);if(length < 0){printf("Recieve Data From Server %s Failed!\n", argv[1]); exit(1);}printf("\n%s\n",buffer);bzero(buffer,BUFFER_SIZE);bzero(buffer,BUFFER_SIZE);strcpy(buffer,"Hello, World! From Client\n");send(client_socket,buffer,BUFFER_SIZE,0);if((stream = fopen("data","w+t"))==NULL){printf("The file 'data' was not opened! \n");}elsebzero(buffer,BUFFER_SIZE);length = 0;while( length = recv(client_socket,buffer,BUFFER_SIZE,0)) {if(length < 0){printf("Recieve Data From Server %s Failed!\n", argv[1]); break;}int write_length = fwrite(buffer,sizeof(char),length,stream); if (write_length<length){printf("File is Write Failed\n");break;}bzero(buffer,BUFFER_SIZE);}printf("Recieve File From Server[%s] Finished\n", argv[1]); fclose(stream);close(client_socket);return 0;}。
