澳门新萄京官方网站-www.8455.com-澳门新萄京赌场网址

澳门新萄京官方网站:让Tiny服务器运行起来,深

2019-12-12 作者:澳门新萄京官方网站   |   浏览(108)

  这段时间上学到了《深远精晓Computer体系》的第11章互连网编制程序,在最后生机勃勃节是多个名叫Tiny的微型web服务器的贯彻,源代码书中生龙活虎度交由,这里就不再复制粘贴了。那篇小博客主要记录一下课后题10的解答。原标题为:
     写出CGI adder函数的HTML表单。你的表单应该富含八个文本框,客户将索要相加的五个数字填在这里多少个文本框中。你的表单应该利用GET方法哀告内容。
     因为小编在此早前没接触过HTML表单,先百度之,找到了w3school的HTML教材,看了一下表单的片段,写出了多少个很简短的小表单,命名称叫index.html:

《深切了然Computer类别》tiny服务器——1,浓厚精通Computer种类

  近年来上学到了《深切明白Computer类别》的第11章网络编制程序,在结尾风姿罗曼蒂克节是二个名称为Tiny的小型web服务器的兑现,源代码书中已经提交,这里就不再复制粘贴了。那篇小博客紧要记录一下课后题10的解答。原标题为:
     写出CGI adder函数的HTML表单。你的表单应该包蕴五个文本框,客户将急需相加的八个数字填在这里三个文本框中。你的表单应该使用GET方法乞请内容。
     因为小编原先没接触过HTML表单,先百度之,找到了w3school的HTML教材,看了须臾间表单的有的,写出了二个非常粗略的小表单,命名称叫index.html:

 1 <!DOCTYPE html>
 2 <html>
 3 <body>
 4 
 5 <p>
 6 please enter two numbers:<br>
 7 </p>
 8 
 9 <form action="/cgi-bin/adder">
10   The first number:
11   <input type="number" name="num1"> <br>
12   The second number:
13   <input type="number" name="num2"> <br>
14   <input type="submit" value="Submit">
15 </form>
16 
17 </body>
18 </html>

  那是输入localhost:8888现在浏览器突显的效劳图。8888是自家设置的tiny的端口,至于为何未有后边的/index.html,是因为本身在源代码师长index.html设为了主界面。

澳门新萄京官方网站 1

  大家得以任由输入多少个数字,点击Submit按键,结果必然是相当的。。

澳门新萄京官方网站 2

  如上图所示,结果显示的是0。注意在该网页的地点栏处,大家见到"localhost:8888/cgi-bin/adder?num1=22&num2=22",看过tiny源码大家就能精晓,adder.c所要深入分析的数额是在&符号两侧的纯数字,也等于说,要想正确的被adder.c程序求和,地址栏应该显得"localhost:8888/cgi-bin/adder?22&22"才对。现身上海教室中的错误的缘故就算,adder程序未有得到七个参数的数值大小。消除措施很简短,只需求在adder.c程序里把四个数字抽取来就能够了,整个adder.c代码如下所示:

 1 #include "net.h"
 2 
 3 int main(void)
 4 {
 5     char *buf, *p;
 6     char arg1[MAXLINE], arg2[MAXLINE], content[MAXLINE];
 7     char tmp[MAXLINE];
 8     int n1 = 0, n2 = 0;
 9 
10     if ( (buf = getenv("QUERY_STRING")) != NULL) {
11         p = strchr(buf, '&');
12         *p = '';
13 
14         strcpy(arg1, buf);
15         strcpy(arg2, p 1);
16 
17         //用来取出两个参数的代码
18         p = strchr(arg1, '=');
19         strcpy(arg1, p 1);
20         p = strchr(arg2, '=');
21         strcpy(arg2, p 1);
22 
23         n1 = atoi(arg1);
24         n2 = atoi(arg2);
25     }
26 
27     sprintf(content, "QUERY_STRING = %s", buf);
28     sprintf(content, "Welcome to add.com: ");
29     //sprintf(content, "arg1=%s, arg2=%sn", arg1, arg2);  调试输出参数
30     sprintf(content, "%sThe Internet addition portal.rn<p>", content);
31     sprintf(content, "%sThe answer is: %d   %d = %drn<p>",
32             content, n1, n2, n1   n2);
33     sprintf(content, "%sThanks for visiting!rn", content);
34 
35     //generate the http response
36     printf("Connection: closern");
37     printf("Content-length: %drn", (int)strlen(content));
38     printf("Content-type: text/htmlrnrn");
39     printf("%s", content);
40     fflush(stdout);
41 
42     exit(0);
43 }

  重新编写翻译adder.c之后,大家重新在浏览器输入网站:localhost:8888,输入五个数字,结果如图:

澳门新萄京官方网站 3

  至此,大家上学Tiny的首先品级就是完事了,实现了课后题11.10的要求,能够处理来自浏览器的静态央求和动态哀告。可是,由于大家的Tiny一遍只好管理几个总是,功能太低了。下风流浪漫节我们就要对Tiny举办一下校订,使其能够扶助并发管理。

这段日子攻读到了《深刻了然计算机连串》的第11章互联网编程,在最终焕发青大年是风流倜傥...

从前写了《深切通晓Computer种类》风流倜傥书中的Tiny服务器的源码拆解深入分析,不过书中并未介绍怎么样运营Tiny,下边就介绍下怎么让Tiny运维起来。

CGIC简明教程

 1 <!DOCTYPE html>
 2 <html>
 3 <body>
 4 
 5 <p>
 6 please enter two numbers:<br>
 7 </p>
 8 
 9 <form action="/cgi-bin/adder">
10   The first number:
11   <input type="number" name="num1"> <br>
12   The second number:
13   <input type="number" name="num2"> <br>
14   <input type="submit" value="Submit">
15 </form>
16 
17 </body>
18 </html>

Tiny的源文件有tiny.c、csapp.c和csapp.h四个。其余要在根目录下新建cgi-bin目录用于存放CGI程序。

本体系的目标是身体力行怎么着使用C语言的CGI库“CGIC”完成Web开荒的各个供给。

  那是输入localhost:8888事后浏览器展现的效用图。8888是本人设置的tiny的端口,至于何以平素不前边的/index.html,是因为小编在源代码上校index.html设为了主分界面。

深深驾驭计算机种类(原书第2版卡塔尔国 PDF清晰汉语版  http://www.linuxidc.com/Linux/2015-03/114720.htm

*********************************

澳门新萄京官方网站 4

方法一:

1.将全数源文件tiny.c、csapp.c和csapp.h放在同一个目录下。别的在同等目录下放置photo.jpg作为测验文件。使用命令:

$gcc -o tiny tiny.c csapp.c -lpthread

  注:加-lpthread是因为csapp.c中大概函数用了四线程库
2.将测量试验用CGI程序嵌入cgi-bin目录下,并编写翻译成可执路程序

$gcc -o adder adder.c

3.运行Tiny程序,并点名端口号(1024–49151可用,别的为资深端口卡塔尔国

$./tiny 1024

4.现行反革命Tiny已经运维起来了,打开浏览器就足以采访了
访谈静态内容
澳门新萄京官方网站 5
会见动态内容
澳门新萄京官方网站 6

    根基知识
       1.运用CGIC的基本思路
       2.获得Get乞请字符串
       3.反转义
       4.获取哀告中的参数值
    进阶练习
       5.用CGIC达成公文上传
*********************************

  我们得以随便输入三个数字,点击Submit按键,结果必然是不对的。。

方式二:使用Makefile完毕Tiny的编写翻译链接:

前风姿洒脱段时间看过Makefile的局地知识,所以本身就试一下用make命令来运营Tiny。

1.与格局一莫衷一是的是,在干活目录下新建include目录,把csapp.h放置到该目录下。然后编写Makefile如下

CFLAGS= -Wall -g -I./include 
LIBS=-lpthread

tiny: tiny.o csapp.o 
    cc -o tiny tiny.o csapp.o $(LIBS)

clean:
    rm *.o tiny 

  Makefile中行使CFLAGS设置编写翻译参数并点名头文件的岗位为./include。用LIBS钦点要链接的库。
2.在劳作目录中输入指令make,就能够到位Tiny的编写翻译链接。
澳门新萄京官方网站 7
3.继承的操作与措施一是如出后生可畏辙的,不再赘言

本文长久更新链接地址:http://www.linuxidc.com/Linux/2015-04/116046.htm

澳门新萄京官方网站 8

1:使用CGIC的基本思路澳门新萄京官方网站,

澳门新萄京官方网站 9

C语言编制程序是风流倜傥项复杂且易于失误的做事,所以在成就复杂职分时,一定要选拔适当的库。对于用C语言编写CGI程序则更是如此。
CGIC是非常理想的C语言CGI库函数。 其下载地址为:www.boutell.com/cgic/#obtain,未来的版本号是2.05。
本站从后日开班,将日益介绍如何行使CGIC落成各个操作,也得以说是八个Tutorial。
(注:本连串关系的编程情状都以Linux,Windows顾客供给对用到的操作系统命令稍作改良)

  如上海教室所示,结果呈现的是0。注旨在该网页的地点栏处,大家看见"localhost:8888/cgi-bin/adder?num1=22&num2=22",看过tiny源码大家就能通晓,adder.c所要剖析的数量是在&符号两侧的纯数字,约等于说,要想准确的被adder.c程序求和,地址栏应该显得"localhost:8888/cgi-bin/adder?22&22"才对。现身上航海用教室中的错误的缘故就是,adder程序未有博得四个参数的数值大小。解决方法很简短,只供给在adder.c程序里把多少个数字抽取来就能够了,整个adder.c代码如下所示:

本文纲要 :
CGIC的安装、测量试验安装、使用CGIC的基本思路;
1卡塔尔国 CGIC的下载安装

 1 #include "net.h"
 2 
 3 int main(void)
 4 {
 5     char *buf, *p;
 6     char arg1[MAXLINE], arg2[MAXLINE], content[MAXLINE];
 7     char tmp[MAXLINE];
 8     int n1 = 0, n2 = 0;
 9 
10     if ( (buf = getenv("QUERY_STRING")) != NULL) {
11         p = strchr(buf, '&');
12         *p = '';
13 
14         strcpy(arg1, buf);
15         strcpy(arg2, p 1);
16 
17         //用来取出两个参数的代码
18         p = strchr(arg1, '=');
19         strcpy(arg1, p 1);
20         p = strchr(arg2, '=');
21         strcpy(arg2, p 1);
22 
23         n1 = atoi(arg1);
24         n2 = atoi(arg2);
25     }
26 
27     sprintf(content, "QUERY_STRING = %s", buf);
28     sprintf(content, "Welcome to add.com: ");
29     //sprintf(content, "arg1=%s, arg2=%sn", arg1, arg2);  调试输出参数
30     sprintf(content, "%sThe Internet addition portal.rn<p>", content);
31     sprintf(content, "%sThe answer is: %d   %d = %drn<p>",
32             content, n1, n2, n1   n2);
33     sprintf(content, "%sThanks for visiting!rn", content);
34 
35     //generate the http response
36     printf("Connection: closern");
37     printf("Content-length: %drn", (int)strlen(content));
38     printf("Content-type: text/htmlrnrn");
39     printf("%s", content);
40     fflush(stdout);
41 
42     exit(0);
43 }

从上边提供的法定网站下载了CGIC库之后,解开压缩包,里面有大约十二个公文,有用的是:
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卡塔尔国 测量试验安装

  重新编写翻译adder.c之后,大家再度在浏览器输入网站:localhost:8888,输入七个数字,结果如图:

在起头编写制定你协和的CGI程序以前,必需求先走通他的例证程序,免得后来程序出错的时候还不知情是安插万分,如故你的程序代码有题目。
咱俩用他自带cgictest.c来落到实处和睦的第多少个C语言CGI程序。
你能够新建三个办事目录,用于寄放你的CGI程序源代码,把cgic.h, cgic.c, cgictest.c八个公文拷贝到那个目录,然后营造四个Makefile文件,其剧情为:

澳门新萄京官方网站 10

    1. test.cgi:cgictest.c cgic.h cgic.c
   2. gcc -wall cgictest.c cgic.c -o test.cgi

  至此,我们上学Tiny的首先等级正是完事了,实现了课后题11.10的渴求,能够管理来自浏览器的静态央浼和动态央求。可是,由于大家的Tiny二次只好管理一个连接,效能太低了。下意气风发节我们将在对Tiny举行一下改正,使其能够帮忙并发处理。

急需提示的是,第二行初阶一定是一个tab键(且独有二个),无法采纳空格。
保存好Makefile的剧情之后,试行make命令:
make

咱俩看见,当前目录下应当多了多少个test.cgi文件。

在您的网址根目录下创设贰个cgi-bin目录(当然名字能够任性取,但作为习贯,平日叫做cgi-bin),然后在Apache的安顿文件里予以其进行CGI代码的权柄,权限校勘完之后要重启Apache。完毕现在,把刚刚变动的test.cgi放到cgi-bin目录中。当时大家得以在浏览器中输入以下地方举行访问:
http://127.0.0.1/cgi-bin/test.cgi

比如符合规律的话,应该看见多个网页被出示出来。那样,第一个C语言的CGI程序就运维起来了。
只要浏览器报错,那么多半是布署Apache的时候有一些操作未有科学实现。
3卡塔尔(قطر‎ 使用CGIC的基本思路

从cgic.c的代码能够看看,它定义了main函数,而在cgictest.c中定义了一个cgiMain函数。也正是说,对于使用CGIC编写的 CGI程序,都以从cgic.c中的代码进入,在库函数完成了少年老成多元需求的操作(举个例子拆解剖析参数、获取系统碰到变量)之后,它才会调用你的代码(从您定义的 cgiMain步向)。

除此以外一些正是,cgi程序输出HTML页面包车型大巴艺术都以选用printf把页面风华正茂行生龙活虎行地打字与印刷出来,比如cgictest.c中的那生机勃勃段代码:
fprintf(cgiOut, "<textarea NAME="address" ROWS=4 COLS=40>n");
fprintf(cgiOut, "Default contents go here. n");
fprintf(cgiOut, "</textarea>n");

上边这段代码的运维结果便是在页面上输出四个textarea。第八个参数cgiOut实际上就是stdin,所以我们能够一贯利用printf,而不用接收fprintf。但是在调整的时候会用到fprintf来重定向输出。
这种艺术与Java Servlet极其临近,Servlet也是经过调用打字与印刷语句System.out.println(…卡塔尔(قطر‎来输出一个页面。(可是后来Java推出了JSP来摆平这种不方便。)
然则与Servlet差异之处在于,使用C语言的大家还要和煦输出HTML底部(证明文书档案类型):
cgiHeaderContentType("text/html");

这些讲话的调用必必要在有着printf语句早先。而以此讲话推行的天职实际便是:
void cgiHeaderContentType(char *mimeType) {
     fprintf(cgiOut, "Content-type: %srnrn", mimeType);
}

以此讲话告诉浏览器,本次传来的数目是何许项目,是一个HTML文书档案,依然三个bin文件… 若是是个HTML文书档案,就经过浏览器窗口展现,如果是一个bin(二进制)文件,则展开下载窗口,让顾客选拔是不是保存文件以至保存文件的渠道。

明白了这几点之后,你就足以编写制定自身的CGIC程序了。新建贰个文本test.c试试:
下载: test.c

    1. #include <stdio.h>
   2. #include "cgic.h"
   3. #include <string.h>
   4. #include <stdlib.h>
   5. int cgiMain() {
   6.     cgiHeaderContentType("text/html");
   7.     fprintf(cgiOut, "<HTML><HEAD>n");
   8.     fprintf(cgiOut, "<TITLE>My First CGI</TITLE></HEAD>n");
   9.     fprintf(cgiOut, "<BODY><H1>Hello CGIC</H1></BODY>n");
  10.     fprintf(cgiOut, "</HTML>n");
  11.     return 0;
  12. }

把Makefile文件中的cgitest.c全体换称test.c,保存,再执行make命令就可以。
这时候通过浏览器访谈,会在页面上看出多个大大的“Hello CGIC”。

2:获取Get央求字符串

Get乞求正是大家在浏览器地址栏输入UEscortL时发送伏乞的法子,或许大家在HTML中定义二个表单(form)时,把action属性设为“Get”时的劳作措施;

Get乞请字符串正是跟在U奥迪Q7L前面以问号“?”早先的字符串,但不包罗问号。举例那样的四个号令:
http://127.0.0.1/cgi-bin/out.cgi?ThisIsTheGetString

在上头这么些U兰德酷路泽L中,“ThisIsTheGetString”就是Get须要字符串。

在走入我们和谐编辑的cgi代码在此以前,CGIC库已经先行把这一个字符串取到了,大家能够在程序中央直属机关接获取,要做的唯有是在您编写的cgiMain方法前边参预以投注解:
extern char *cgiQueryString;

今昔提交多少个轻巧的例证,这一个例子跟上大器晚成篇的测量试验程序特别类似,只不进度序的出口是使用者输入的Get央求字符串。
下载: test.c

    1. #include <stdio.h>
   2. #include "cgic.h"
   3. #include <string.h>
   4. #include <stdlib.h>
   5. 
   6. extern char *cgiQueryString;
   7. int cgiMain() {
   8.     cgiHeaderContentType("text/html");
   9.     fprintf(cgiOut, "<HTML><HEAD>n");
  10.     fprintf(cgiOut, "<TITLE>My CGIC</TITLE></HEAD>n");
  11.     fprintf(cgiOut, "<BODY>");
  12.     fprintf(cgiOut, "<H1>%s</H1>",cgiQueryString);
  13.     fprintf(cgiOut, "</BODY>n");
  14.     fprintf(cgiOut, "</HTML>n");
  15.     return 0;
  16. }

假定把这一个程序编写翻译成out.cgi(编写翻译方法参见上一篇),并安顿到Web服务器的cgi-bin目录下,当客商在浏览器地址栏输入本文此前给出的U昂CoraL字符串时,浏览器页面上会展现:
ThisIsTheGetString

作者们也得以编写一个用以测量试验的HTML页面:
下载: test.html

    1. <html>
   2. <head>
   3.     <title>Test</title>
   4. </head>
   5. <body>
   6.     <form action="cgi-bin/out.cgi" method="get">
   7.         <input type="text" name="theText">
   8.         <input type="submit" value="Continue →">
   9.     </form>
  10. </body>
  11. </html>

文本的布局组织应为:
|test.html
|—-cgi-bin/out.cgi

世家能够实施,通过浏览器访问http://127.0.0.1/test.html,在文本框内输入一些字符,并点击提交开关,然后就足以看看cgi程序的实行结果:把在文本框输入的字符原样显示在浏览器上。

3:反转义

浏览器在发送Get央浼时,会把诉求字符串进行转义操作(英文术语为: escape); 比方,我们在地方栏输入(注意最后”it’s me”中的空格):
http://localhost/~Jack/cgi-bin/out.cgi?it's me

浏览器会把它转义为:
http://localhost/~Jack/cgi-bin/out.cgi?it's me

在上大器晚成篇最后交给的例证中,若是在文本框内输入
it's me

你会意识,浏览器最后发送的呼吁为
http://localhost/~Jack/cgi-bin/out.cgi?theText=it's me

透过CGIC,大家能够把那个被转义后的字符还原为大家自然的输入,那么些历程就叫“反转义” (Unescape卡塔尔国。
不过那些历程有一些像hack他的代码。

方方面面进程分四个步骤:
1)展开cgic.c,找到这风度翩翩行语句:
static cgiUnescapeResultType cgiUnescapeChars(char **sp, char *cp, int len);

只顾,大家要找的只是以此函数注脚,不是函数定义;

2)在这里个函数证明语句的上边,你拜候到二个构造体定义:

    1. typedef enum {
   2.     cgiUnescapeSuccess,
   3.     cgiUnescapeMemory
   4. } cgiUnescapeResultType;

把这几行语句复制到cgic.h文件中,并在这里间把它注释掉;
何况还要删除在第一步中找到的函数表明语句中的“static”关键字。

3)大家明日就能够使用反转义函数cgiUnescapeChars了:
在您本人的代码(根据常规,照旧test.c)中,到场以下证明语句就能够
extern cgiUnescapeResultType cgiUnescapeChars(char **sp, char *cp, int len);

接下去大家付出生机勃勃段完整的test.c代码
下载: test.c

    1. #include <stdio.h>
   2. #include "cgic.h"
   3. #include <string.h>
   4. #include <stdlib.h>
   5. 
   6. extern char *cgiQueryString;
   7. extern cgiUnescapeResultType cgiUnescapeChars(char **sp, char *cp, int len);
   8. int cgiMain() {
   9.     char * buffer;
  10.     cgiHeaderContentType("text/html");
  11.     fprintf(cgiOut, "<HTML><HEAD>n");
  12.     fprintf(cgiOut, "<TITLE>My CGI</TITLE></HEAD>n");
  13.     fprintf(cgiOut, "<BODY>");
  14.     cgiUnescapeChars(&buffer, cgiQueryString, strlen(cgiQueryString));
  15.     fprintf(cgiOut, "<H1>%s</H1>",buffer);
  16.     fprintf(cgiOut, "</BODY>n");
  17.     fprintf(cgiOut, "</HTML>n");
  18.     free(buffer);
  19.     return 0;
  20. }

值得注意的是,buffer的仓库储存空间是cgiUnescapeChars帮你分配的,但结尾要由你和睦来刑释(free),那点千万不得淡忘。

下边你能够整合上风度翩翩篇给出的测量试验用html代码试试该cgi程序的周转结果,也得以一直在浏览器地址栏输入一些分包特殊符号的字符串。

最终讲一下为啥一定要用这种骇客的秘技来成功该职责,而CGIC不显式提供?
CGIC的观点是,大家平日只要求剖判号召中的键值对,比如:”?q=nice&client=IE”,当大家在服务端查询“q”的值时,大家就能够得到“nice”。CGIC有风流潇洒族函数帮忙大家做到那个职分,比方cgiFormString(未来会讲到)。在分条析理这种央求格式的时候,要是大家提供的参数值含有被转义的字符,那么CGIC就能够在里边调用cgiUnescapeChars完毕反转义。
不过,临时候大家会发送极其复杂的Get央求字符串,但并非“键-值”对的格式。那就必要直接行使cgiUnescapeChars实行反转义了。
比方:假如大家有个服务端cgi程序chat.cgi,那是个互连网闲聊机器人(可能你能够支付和谐的Web版MSN机器人、QQ机器人)。若是大家发送如下央求:
http://127.0.0.1/cgi-bin/chat.cgi?"this is a cgi user"

那么chat.cgi就可以把“this is a cgi user”当作你对它说的话,经过管理,它会过来一段语句。为了方便,大家并不曾写成“键-值”对的款式。这时被大家hack的cgiUnescapeChars就会派上用场了。

4:获取诉求中的参数值

我们在交付二个表单(form卡塔尔时,怎样把表单内的值提收取来吧?
比如上边这一个表单:
<form action="cgi-bin/out.cgi" method="POST">
     <input type="text" name="name" />
    <input type="text" name="number" />
    <input type="submit" value="Submit" />
</form>

当out.cgi收到央求时,须求把输入框”name”和输入框”number”内的值提抽取来。况兼不管form中的action是GET依然POST,都要管用。

上边给出示例代码:
下载: test.c

    1. #include <stdio.h>
   2. #include "cgic.h"
   3. #include <string.h>
   4. #include <stdlib.h>
   5. 
   6. int cgiMain() {
   7.     char name[241];
   8.     char number[241];
   9.     cgiHeaderContentType("text/html");
  10.     fprintf(cgiOut, "<HTML><HEAD>n");
  11.     fprintf(cgiOut, "<TITLE>My CGI</TITLE></HEAD>n");
  12.     fprintf(cgiOut, "<BODY>");
  13.     cgiFormString("name", name, 241);
  14.     cgiFormString("number", number, 241);
  15.     fprintf(cgiOut, "<H1>%s</H1>",name);
  16.     fprintf(cgiOut, "<H1>%s</H1>",number);
  17.     fprintf(cgiOut, "</BODY>n");
  18.     fprintf(cgiOut, "</HTML>n");
  19.     return 0;
  20. }

从地点的代码能够观望,第13行和第14行得到了输入框的值。

赢得输入参数值在CGIC中实际有生机勃勃族函数,cgiFormString是中间最常用的贰个。
cgiFormStringNoNewlines用来去掉换行符(假设客户是在一个TextArea里输入字符的话);
cgiFormStringSpaceNeeded 用于测量检验输入值的长度,能够以此为依据,然后按需正确分配缓冲区。

5.用C语言库(CGIC卡塔尔(قطر‎编写CGI,完毕公文上传

澳门新萄京官方网站:让Tiny服务器运行起来,深入理解计算机系统。用C语言编写cgi程序的话,多半会用到CGIC。这是个非常流行的库,遇到文件上传之类的利用越来越离不开它。官方页面及下载地址为:www.boutell.com/cgic/#obtain

成都百货上千网址都有文件上传的功能,本文呈现什么用CGIC库编写文件上传的服务端程序,最后交给风流洒脱段轻易的HTML代码,供大家测量试验使用。
下载: upload.c

    1. #include<stdio.h>
   2. #include<string.h>
   3. #include<unistd.h>
   4. #include<fcntl.h>
   5. #include<sys/stat.h>
   6. #include"cgic.h"
   7. #define BufferLen 1024
   8. int cgiMain(void){
   9.     cgiFilePtr file;
  10.     int targetFile;
  11.     mode_t mode;
  12.     char name[128];
  13.     char fileNameOnServer[64];
  14.     char contentType[1024];
  15.     char buffer[BufferLen];
  16.     char *tmpStr=NULL;
  17.     int size;
  18.     int got,t;
  19.     cgiHeaderContentType("text/html");
  20.     //得到html页面中file成分的值,应该是文本在顾客机上的路线名
  21.     if (cgiFormFileName("file", name, sizeof(name)) !=cgiFormSuccess) {
  22.         fprintf(stderr,"could not retrieve filenamen");
  23.         goto FAIL;
  24.     }
  25.     cgiFormFileSize("file", &size);
  26.     //获得文件类型,然则本例中并未有使用
  27.     cgiFormFileContentType("file", contentType, sizeof(contentType));
  28.     //近些日子文件存在于系统不经常文件夹中,平常为/tmp,通过该命令展开不常文件。有的时候文件的名字与客商文件的名字差异,所以不能够透过路线/tmp/userfilename的方法获得文件
  29.     if (cgiFormFileOpen("file", &file) != cgiFormSuccess) {
  30.         fprintf(stderr,"could not open the filen");
  31.         goto FAIL;
  32.     }
  33.     t=-1;
  34.     //从路线名解析出客户文件名
  35.     while(1){
  36.         tmpStr=strstr(name t 1,"\");
  37.         if(NULL==tmpStr)
  38.         tmpStr=strstr(name t 1,"/");//if "\" is not path separator, try "/"
  39.         if(NULL!=tmpStr)
  40.             t=(int)(tmpStr-name);
  41.         else
  42.             break;
  43.     }
  44.     strcpy(fileNameOnServer,name t 1);
  45.     mode=S_IRWXU|S_IRGRP|S_IROTH;
  46.     //在当前目录下树立新的文本,第贰个参数实际上是路径名,此处的意思是在cgi程序所在的目录(当前目录))创立新文件
  47.     targetFile=open(fileNameOnServer,O_RDWR|O_CREAT|O_TRUNC|O_APPEND,mode);
  48.     if(targetFile<0){
  49.         fprintf(stderr,"could not create the new file,%sn",fileNameOnServer);
  50.         goto FAIL;
  51.     }
  52.     //从系统偶然文件中读出文件内容,并置于刚(Yu-Gang卡塔尔创建的目的文件中
  53.     while (cgiFormFileRead(file, buffer, BufferLen, &got) ==cgiFormSuccess){
  54.         if(got>0)
  55.             write(targetFile,buffer,got);
  56.     }
  57.     cgiFormFileClose(file);
  58.     close(targetFile);
  59.     goto END;
  60. FAIL:
  61.     fprintf(stderr,"Failed to upload");
  62.     return 1;
  63. END:
  64.     printf("File "%s" has been uploaded",fileNameOnServer);
  65.     return 0;
  66. }

假使该文件存款和储蓄为upload.c,则利用如下命令编辑:
gcc -Wall upload.c cgic.c -o upload.cgi

编写翻译实现后把upload.cgi复制到你安插cgi程序的目录(常常命名字为cgi-bin)。
正式陈设时,请必需改进用open创造新文件那生机勃勃行代码。把open的首先个参数设置为指标文件在服务器上囤积的相对路线,可能相对于cgi程序的相对路线。本例中,出于轻巧思谋,在cgi程序所在目录下开立异文件。

测试用HTML代码:
下载: upload.html

    1. <form target="_blank" method="post" action="cgi-bin/upload.cgi">
   2.     <input name="file" type="file" /> <input name="submit" type="submit" />
   3. </form>

终极的文件目录布局为
/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的源代码就能够):

    1. else if (cgiStrEqNc(cgiContentType, "multipart/form-data")) {
   2. #ifdef CGICDEBUG
   3. CGICDEBUGSTART
   4.     fprintf(dout, "Calling PostMultipartInputn");
   5. CGICDEBUGEND
   6. #endif
   7. //小编的代码
   8. //UpSize:文件长度上限值,以byte为单位,UpSize是三个int变量,因为cgiContentLength的品种为int
   9.     if(cgiContentLength>UpSize){
  10.         cgiHeaderContentType("text/html");
  11.         printf("File too large!n");
  12.         cgiFreeResources();
  13.         return -1;
  14.     }
  15. //小编的代码甘休
  16.     if (cgiParsePostMultipartInput() != cgiParseSuccess) {
  17. #ifdef CGICDEBUG
  18. CGICDEBUGSTART
  19.         fprintf(dout, "PostMultipartInput failedn");
  20. CGICDEBUGEND
  21. #endif
  22.         cgiFreeResources();
  23.         return -1;
  24.     }
  25. #ifdef CGICDEBUG
  26. CGICDEBUGSTART
  27.     fprintf(dout, "PostMultipartInput succeededn");
  28. CGICDEBUGEND
  29.     #endif
  30. }
  31. }

变量UpSize代表文件大小的上限。在cgic.c的main中找到有关代码,并改正成下边那样就能够。你能够在cgic.c中定义UpSize,也能够在刚刚完结的upload.c中定义,然后在cgic.c中用extern方式援用。

 

原稿地址

本文由澳门新萄京官方网站发布于澳门新萄京官方网站,转载请注明出处:澳门新萄京官方网站:让Tiny服务器运行起来,深

关键词: