betway必威-betway必威官方网站
做最好的网站

betway必威:目录显示等

三、 测试

此番测验

选用了两台机械。风华正茂台Ubuntu的浏览器作为客商端,一台Redhat作为劳动器端,在那之中Redhat是Ubuntu上依照VirtualBox的大器晚成台设想机。

IP地址音讯如下:Ubuntu的vboxnet0:

<img src="http://jbcdn2.b0.upaiyun.com/2016/11/73d81eee84e5fe07de8e076ee6b5d25a.jpg" alt="betway必威 1" />

RedHateth0:

betway必威 2

RedHat主机编译项目:

betway必威 3

是因为大家同事监听了8000和4444,所以有七个进度运行。

HTTP的首页:

betway必威 4

betway必威,目录彰显效果:

betway必威 5

HTTP GET页面:

betway必威 6

HTTPGET响应:

betway必威 7

从HTTP GET响应中大家观察UEvoqueL,参数实在是透过U讴歌ZDXL传送过去的。

其中getAuth.c如下:

#include "wrap.h"  
#include "parse.h"  

int main(void) {  
    char *buf, *p;  
    char name[MAXLINE], passwd[MAXLINE],content[MAXLINE];  

    /* Extract the two arguments */  
    if ((buf = getenv("QUERY_STRING")) != NULL) {  
    p = strchr(buf, '&');  
    *p = '\0';  
    strcpy(name, buf);  
    strcpy(passwd, p 1);  
    }  

    /* Make the response body */  
    sprintf(content, "Welcome to auth.com:%s and %srn<p>",name,passwd);  
    sprintf(content, "%srn", content);  

    sprintf(content, "%sThanks for visiting!rn", content);  

    /* Generate the HTTP response */  
    printf("Content-length: %drn", strlen(content));  
    printf("Content-type: text/htmlrnrn");  
    printf("%s", content);  
    fflush(stdout);  
    exit(0);  
}

HTTPS的首页:由于我们的CA不可信,所以需求大家承认

betway必威 8

认可后HTTPS首页:

betway必威 9

HTTPS POST页面:

betway必威 10

HTTPS POST响应:

betway必威 11

从上大家得以看来,POST提交的参数的确不是透过USportageL传送的。

2、各模块功能介绍

头文件httpd.h,包蕴该品种代码所接纳的整整函数的头文件以致宏定义,和函数证明;

 1 #ifndef _HTTPD_
 2 #define _HTTPD_
 3 
 4 #include <stdio.h>
 5 #include <stdlib.h>
 6 #include <sys/socket.h>
 7 #include <sys/types.h>
 8 #include <netinet/in.h>
 9 #include <arpa/inet.h>
10 #include <fcntl.h>
11 #include <errno.h>
12 #include <string.h>
13 #include <unistd.h>
14 #include <sys/stat.h>
15 #include <sys/wait.h>
16 
17 #define SUCCESS 0 
18 #define NOTICE  1
19 #define WARNING 2
20 #define ERROR   3
21 #define FATAL   4
22 
23 #define SIZE 1024
24 
25 void print_log(char *msg, int level); //打印日志
26 int startup(const char *ip, int  port); //创建监听套接字
27 void *handler_request(void *arg);  //处理请求
28 
29 #endif

main函数文件main.c达成重大通讯逻辑,通过socket建设构造连接的,监听和担任套接字,然后创制新线程处理诉求。

 1 #include <pthread.h>
 2 #include "httpd.h"
 3 
 4 static void usage(const char *proc)
 5 {
 6     printf("Usage: %s [local_ip] [local_port]n", proc);
 7 }
 8 
 9 int main(int argc, char *argv[])
10 {
11     if(argc != 3){
12         usage(argv[0]);
13         return 1;
14     }
15 
16     int listen_sock = startup(argv[1], atoi(argv[2]));//监听套接字
17     //daemon(0, 0);
18     while(1){
19         struct sockaddr_in client;
20         socklen_t len = sizeof(client);
21         int new_sock = accept(listen_sock, (struct sockaddr*)&client, &len);//接收套接字
22         if(new_sock < 0){
23             print_log(strerror(errno), NOTICE);
24             continue;
25         }
26 
27         printf("get client [%s:%d]n",
28                 inet_ntoa(client.sin_addr),
29                 ntohs(client.sin_port)); //链接到一个客户端之后打印其IP及端口号
30 
31         pthread_t id;
32         int ret = pthread_create(&id, NULL, //创建新线程
33                 handler_request, (void *)new_sock);
34         if(ret != 0){
35             print_log(strerror(errno), WARNING);
36             close(new_sock);
37         }else{
38             pthread_detach(id); //将子线程分离,该线程结束后会自动释放所有资源
39         }
40     }
41     close(listen_sock);
42     return 0;
43 }

模块效能函数在httpd.c文件

  1 #include "httpd.h"
  2 
  3 void print_log(char *msg, int level)
  4 {
  5 #ifdef _STDOUT_
  6     const char * const level_msg[]={
  7         "SUCCESS",
  8         "NOTICE",
  9         "WARNING",
 10         "ERROR",
 11         "FATAL",
 12     };
 13     printf("[%s][%s]n", msg, level_msg[level%5]);
 14 #endif
 15 }
 16 
 17 int startup(const char *ip, int  port)  //
 18 {
 19     int sock = socket(AF_INET, SOCK_STREAM, 0);  //创建套接字
 20     if(sock < 0){
 21         print_log(strerror(errno), FATAL); //strerror()将错误码转换为对应的错误码描述
 22         exit(2);
 23     }
 24 
 25     int opt = 1;
 26     setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));  //将该套接字设置为地址复用状态,若服务器挂掉可实现立即重启
 27 
 28     struct sockaddr_in local;
 29     local.sin_family = AF_INET;
 30     local.sin_port = htons(port);  //端口号转换
 31     local.sin_addr.s_addr = inet_addr(ip);  //ip转换
 32     if(bind(sock, (struct sockaddr*)&local, sizeof(local)) < 0){  //绑定
 33         print_log(strerror(errno), FATAL);
 34         exit(3);
 35     }
 36     if(listen(sock, 10) < 0){  //监听
 37         print_log(strerror(errno), FATAL);
 38         exit(4);
 39     }
 40     return sock;
 41 }
 42 
 43 //ret > 1, line != '\0'读成功,正常字符; ret=1&line='n'  ret<=0&&line=='\0'
 44 static int get_line(int sock, char line[], int size)  //得到一行请求内容
 45 {
 46     // read 1 char , one by one
 47     char c = '\0'; 
 48     int len = 0;
 49     while( c != 'n' && len < size-1){  
 50         int r = recv(sock, &c, 1, 0);  
 51         if(r > 0){                      
 52            if(c == 'r'){
 53                //窥探,只把缓冲区的东西拿出来看看
 54                int ret = recv(sock, &c, 1, MSG_PEEK);
 55                if(ret > 0){
 56                    if(c == 'n'){
 57                        recv(sock, &c, 1, 0);
 58                    }else{
 59                        c = 'n'; 
 60                    }
 61                }
 62            }// r->n rn -> n
 63            line[len  ] = c;
 64         }else{
 65             c = 'n';
 66         }
 67     }
 68     line[len]='\0';
 69     return len;
 70 }
 71 //不同平台下n、r、n r,意义不同,这里将其统一成n
 72 
 73 static void echo_string(int sock)
 74 {}
 75 
 76 static int echo_www(int sock, char *path, int size)
 77 {
 78     int fd = open(path, O_RDONLY);
 79     if(fd < 0){
 80         echo_string(sock);
 81         print_log(strerror(errno), FATAL);
 82         return 8;
 83     }
 84 
 85     const char *echo_line="HTTP/1.0 200 OKrn";   //状态行
 86     send(sock, echo_line, strlen(echo_line), 0);
 87     const char *null_line="rn";
 88     send(sock, null_line, strlen(null_line), 0); //空行
 89 
 90     if(sendfile(sock, fd, NULL, size) < 0){//在内核区实现两个文件描述符的拷贝,不用定义临时变量,省略两次数据拷贝,效率提高
 91         echo_string(sock);
 92         print_log(strerror(errno), FATAL);
 93         return 9;
 94     }
 95 
 96     close(fd);
 97     return 0;
 98 }
 99 
100 static void drop_header(int sock)
101 {
102     char line[1024];
103     int ret = -1;
104     do{
105         ret = get_line(sock, line, sizeof(line));
106     }while(ret>0 && strcmp(line, "n"));
107 }
108 
109 static int exe_cgi(int sock, char *method, 
110         char *path, char *query_string)
111 {
112     int content_len = -1;
113     char method_env[SIZE/10];
114     char query_string_env[SIZE];
115     char content_len_env[SIZE/10];
116 
117     if( strcasecmp(method, "GET") == 0 ){//忽略大小写的字符比较,此处为判断请求资源的方法是否为GET方法
118         drop_header(sock);//如果是GET方法则已从URL中知道用户请求资源所传参数
119     }else{//POST
120         char line[1024];
121         int ret = -1;
122         do{
123             ret = get_line(sock, line, sizeof(line));
124             if(ret > 0 &&
125                strncasecmp(line,"Content-Length: ", 16)== 0){
126                 content_len = atoi(&line[16]);//消息正文字长描述
127             }
128         }while(ret>0 && strcmp(line, "n"));
129         if(content_len == -1){
130             echo_string(sock);
131             return 10;
132         }
133     }
134     const char *echo_line="HTTP/1.0 200 OKrn";  //状态行
135     send(sock, echo_line, strlen(echo_line), 0);  
136     const char *type="Content-Type:text/html;charset=ISO-8859-1rn";
137     send(sock, type, strlen(type), 0);
138     const char *null_line="rn";  
139     send(sock, null_line, strlen(null_line), 0);  //空行
140 
141     printf("query_string: %sn", query_string);
142     //path-> exe
143     int input[2];
144     int output[2];
145     if(pipe(input) < 0 || pipe(output) < 0){
146         echo_string(sock);
147         return 11;
148     }
149     pid_t id = fork();
150     if(id < 0){
151         echo_string(sock);
152         return 12;
153     }else if(id == 0){//child
154         close(input[1]);
155         close(output[0]);
156         sprintf(method_env, "METHOD=%s", method);
157         putenv(method_env);
158 
159         if(strcasecmp(method, "GET") == 0){
160             sprintf(query_string_env, "QUERY_STRING=%s", query_string);
161             putenv(query_string_env);
162         }else{ // POST
163             sprintf(content_len_env, "CONTENT_LENGTH=%d", content_len);
164             putenv(content_len_env);
165         }
166         dup2(input[0], 0);//重定向
167         dup2(output[1], 1);
168         execl(path, path, NULL);  //第一个参数:路径及名字,第二个参数:怎么执行,传什么参数
169         printf("execl error!n");
170         exit(1);
171     }else{
172         close(input[0]);
173         close(output[1]);
174 
175         int i = 0;
176         char c = '\0';
177         if(strcasecmp(method, "POST") == 0){
178             for( ; i < content_len; i   ){
179                 recv(sock, &c, 1, 0);
180                 write(input[1], &c, 1);
181             }
182         }
183 
184         c='\0';
185         while(read(output[0], &c, 1) > 0){
186             send(sock, &c, 1, 0);
187         }
188 
189         waitpid(id, NULL, 0);
190         close(input[1]);
191         close(output[0]);
192     }
193 }
194 
195 //thread 
196 void *handler_request(void *arg) 
197 {
198     int sock = (int)arg;
199 #ifdef _DEBUG_  //测试代码
200     char line[1024];  
201     do{
202         int ret = get_line(sock, line, sizeof(line));
203         if(ret > 0){
204             printf("%s", line);
205         }else{
206             printf("request ...... done!n");
207             break;
208         }
209     }while(1);
210 #else
211     int ret = 0;
212     char buf[SIZE];  //读到的请求内容
213     char method[SIZE/10];  //请求资源的方法
214     char url[SIZE];  //统一资源标识符
215     char path[SIZE];  //有效资源路径
216     int i, j;
217     int cgi = 0; //设置CGI模式
218     char *query_string = NULL;  //请求资源字符串(URL中问号后的内容)
219     if(get_line(sock, buf, sizeof(buf)) <= 0){ //获得一行请求内容
220         echo_string(sock);
221         ret = 5;
222         goto end;
223     }
224     i=0;//method ->index
225     j=0;//buf -> index
226 
227     while( !isspace(buf[j]) &&
228             j < sizeof(buf) &&
229             i < sizeof(method)-1){
230         method[i]=buf[j];
231         i  , j  ;
232     }
233     method[i] = 0;
234     if(strcasecmp(method, "GET") &&  //忽略大小写的字符比较,此处为判断请求资源的方法是否为GET方法或POST方法
235             strcasecmp(method, "POST") ){
236         echo_string(sock);
237         ret = 6;
238         goto end;
239     }
240     if(strcasecmp(method, "POST") == 0){  //如果使用POST方法必定是CGI模式
241         cgi = 1;
242     }
243     //buf -> "GET          /      http/1.0"
244     while(isspace(buf[j]) && j < sizeof(buf)){
245         j  ;
246     }
247     i=0;
248     while(!isspace(buf[j]) && j < sizeof(buf) && i < sizeof(url)-1){
249         url[i] = buf[j];
250         i  , j  ;
251     }
252     url[i] = 0;
253     printf("method: %s, url: %sn", method, url);
254     query_string = url;
255     while(*query_string != '\0'){
256         if(*query_string == '?'){//如果是GET方法且传参,必定是CGI模式
257             *query_string = '\0';
258             query_string  ;
259             cgi = 1;
260             break;
261         }
262         query_string  ;
263     }
264     sprintf(path, "wwwroot%s", url);
265     //method, url, query_string, cgi
266     if(path[strlen(path)-1] == '/'){ // '/'
267         strcat(path, "index.html");//如果是GET方法且无参,拼接上首页信息
268     }
269     struct stat st;
270     if(stat(path, &st) != 0){
271         echo_string(sock);
272         ret = 7;
273         goto end;
274     }else{
275         if(S_ISDIR(st.st_mode)){  //如果是目录,则拼接上首页信息,默认任何目录下都可以访问首页
276             strcat(path, "/index.html");
277         }else if( (st.st_mode & S_IXUSR) ||   //如果是二进制文件
278                   (st.st_mode & S_IXGRP) || 
279                   (st.st_mode & S_IXOTH) ){
280             cgi=1;
281         }else{
282         }
283         //ok->cgi=?, path, query_string, method
284         if(cgi){
285             printf("enter CGIn");  //进入CGI模式处理
286             exe_cgi(sock, method, path, query_string);
287         }else{//非CGI处理
288             printf("method: %s, url: %s, path: %s, cgi: %d, query_string: %sn", method, url, path, cgi, query_string);
289             drop_header(sock); //!!!!!!!!!!!!!!清除信息(不关心的内容)
290             echo_www(sock, path, st.st_size);//非CGI模式时的响应
291         }
292     }
293 
294 end:
295     printf("quit client...n");  //出错退出
296     close(sock);
297     return (void*)ret;
298 #endif
299 }

获取 Cookies

查找全数安装的 cookies 是特别轻便的。cookies 被储存在 CGI 情况变量 HTTP_老总KIE 中,且它们的样式如下:

key1=value1;key2=value2;key3=value3....

上面包车型大巴实例演示了何等赢得 cookies。

#include <iostream>
#include <vector>  
#include <string>  
#include <stdio.h>  
#include <stdlib.h> 

#include <cgicc/CgiDefs.h> 
#include <cgicc/Cgicc.h> 
#include <cgicc/HTTPHTMLHeader.h> 
#include <cgicc/HTMLClasses.h>

using namespace std;
using namespace cgicc;

int main ()
{
   Cgicc cgi;
   const_cookie_iterator cci;

   cout << "Content-type:text/htmlrnrn";
   cout << "<html>n";
   cout << "<head>n";
   cout << "<title>CGI 中的 Cookies</title>n";
   cout << "</head>n";
   cout << "<body>n";
   cout << "<table border = "0" cellspacing = "2">";

   // 获取环境变量
   const CgiEnvironment& env = cgi.getEnvironment();

   for( cci = env.getCookieList().begin();
        cci != env.getCookieList().end(); 
          cci )
   {
      cout << "<tr><td>" << cci->getName() << "</td><td>";
      cout << cci->getValue();                                 
      cout << "</td></tr>n";
   }
   cout << "</table><n";

   cout << "<br/>n";
   cout << "</body>n";
   cout << "</html>n";

   return 0;
}

于今,编写翻译上边包车型客车次第,生成 getcookies.cgi,并尝试采取下边包车型地铁链接获取你的微管理机上有所可用的 cookies:

/cgi-bin/getcookies.cgi

那会发出叁个列表,显示了上意气风发节中装置的八个 cookies 以致你的微型机上全体别的的 cookies:

UserID XYZ 
Password XYZ123 
Domain www.w3cschool.cc 
Path /perl 

以此尤为重要是在CS应用软件底蕴上做的,增加了POST,SSL,目录展现等功用。

1)POST方法

  假诺运用POST方法,那么客商端发送的客商数据将存放在在CGI进度的正式输入中,即新闻正文内,较为蒙蔽,且常常从不上限。相同的时间将客户数据的长短赋予遇到变量中的CONTENT_LENGTH。客商端用POST情势发送数占领一个对应的MIME类型(通用Internet邮件扩大服务:Multi-purpose Internet Mail Extensions)。近来,MIME类型常常是:application/x-wwww-form-urlencoded,该项目表示数据来源HTML表单。该品种记录在条件变量CONTENT_TYPE中,CGI程序应该检查该变量的值。

设置 Cookies

向浏览器发送 cookies 是特简单的。这个 cookies 会在 Content-type 字段以前,与 HTTP 头一同被发送。借让你想设置 UserID 和 Password 为 cookies,设置 cookies 的步骤如下所示:

#include <iostream>
using namespace std;

int main ()
{

   cout << "Set-Cookie:UserID=XYZ;rn";
   cout << "Set-Cookie:Password=XYZ123;rn";
   cout << "Set-Cookie:Domain=www.w3cschool.cc;rn";
   cout << "Set-Cookie:Path=/perl;n";
   cout << "Content-type:text/htmlrnrn";

   cout << "<html>n";
   cout << "<head>n";
   cout << "<title>CGI 中的 Cookies</title>n";
   cout << "</head>n";
   cout << "<body>n";

   cout << "设置 cookies" << endl;  

   cout << "<br/>n";
   cout << "</body>n";
   cout << "</html>n";

   return 0;
}

从这么些实例中,大家询问了什么样设置 cookies。大家采纳 Set-Cookie HTTP 头来设置 cookies。

在此边,有局地装置 cookies 的性子是可选的,例如 Expires、Domain 和 Path。值得注意的是,cookies 是在发送行 "Content-type:text/htmlrnrn 从前被安装的。

编写翻译上边的顺序,生成 setcookies.cgi,并尝试使用上面包车型客车链接设置 cookies。它会在您的Computer上设置四个 cookies:

/cgi-bin/setcookies.cgi

风姿罗曼蒂克、 达成效益:

1.支持GET/POST方法

2.援救SSL安全连接即HTTPS

3.支持CGI

4.基于IP地址和掩码的印证

5.目录突显

6.日记功用

7.错误提醒页面

github地址:

源代码下载地址:点击打开链接

1、项目介绍

  HTTP左券是应用层的面向对象的协商,由于其简捷、连忙的方法,适用于布满式超媒体消息类别。左券的事必躬亲内容,前面少年老成篇HTTP公约详细明白曾经详细介绍了,这里不再赘述。

   项目全体描述:HTTP辅助客商端/服务器格局,终端客户可因而浏览器或互联网爬虫与服务器建构连接,所以首先供给自己作主实现服务器Server端,具体由头文件httpd.h、main函数文件httpd.c、模块功用函数文件httpd.c组成,主要达成顾客端与服务器通过socket创立通讯机制。首先由客商积极发起叁个到服务器上内定端口(默许端口为80)的乞请,服务器则在万分端口监听客商端发送过来的乞请。服务器生机勃勃行生机勃勃行读取央求,通过央求音讯判别客户央浼财富的艺术和路线,若方法和路径没极度,则方法和渠道通过CGI格局或非CGI向顾客提供不相同的HTML网页消息。管理完供给顾客端向客户发送响应,富含意况行如:“HTTP/1.1 200 OK”、响应报头、音信正文,音讯体即为服务器上的能源。

落时间效益果与利益意气风发:静态首页展现(图片、文字文字音信);

落到实处二:扶助表单提交,能够依靠浏览器或telnet工具使用GET、POST方法访问服务器,完毕多少的粗略总结功能;

完结三:引进MYSQL,客户可由此页面表单进行数据操作,服务器得到客商提交的多少后,会把数量存入到远端数据库,客商端也可伸手查看数据库新闻。

总体项指标文件目录:

betway必威 12

目录:
conf:配置文件,贮存须要绑定的服务器的ip和port ;
log:shell的日记文件以至http错误管理的日志文件 ;
sql_client:mysql部分的API及CGI实现;
thread_pool:线程池实现;
wwwroot:web服务器职业的根目录,饱含各类财富页面(例如暗许的index.html页面,差错处理的404页面),以致实施cgi的可实行程序。下面还会有叁个 cgi-bin目录,是贮存在CGI脚本之处。这么些本子使WWW服务器和浏览器能运维外界程序,而不须求运转另四个主次。它是运作在Web服务器上的二个程序,并由来自于浏览者的输入触发。

方方面面项指标框架图:

 betway必威 13

C CGI 库

在切实地工作的实例中,您须要经过 CGI 程序施行非常多操作。这里有一个专为 C 程序而编辑的 CGI 库,大家得以从 ftp://ftp.gnu.org/gnu/cgicc/ 上下载那一个 CGI 库,并根据上边包车型大巴步调安装库:

$tar xzf cgicc-X.X.X.tar.gz 
$cd cgicc-X.X.X/ 
$./configure --prefix=/usr 
$make
$make install

您能够点击 C CGI Lib Documentation,查六柱预测关的库文书档案。

二、设计原理

首先介绍部分HTTP左券基本知识。

#1.GET/POST

本实现援助GET/POST方法,都以HTTP合同供给帮忙的正规措施。

GET方法重若是透过U奥德赛L发送乞请和传送数据,而POST方法在号召头台湾空中大学器晚成格之后传送数据,所以POST方法比GET方法安全性高,因为GET方法能够从来看出传送的数码。此外三个有别于就是GET方法传输的数额相当小,而POST方法超大。所以常常表单,登录页面等都以通过POST方法。

#2.MIME类型

当服务器获取顾客端的呼吁的文件名,将剖判文件的MIME类型,然后告诉浏览器改文件的MIME类型,浏览器通过MIME类型深入分析传送过来的数量。具体来讲,浏览器央浼一个主页面,该页面是叁个HTML文件,那么服务器将”text/html”类型发给浏览器,浏览器通过HTML分析器度和胆识别发送过来的从头到尾的经过并展现。

下边将叙述三个生气勃勃情状。

顾客端应用浏览器通过U凯雷德L发送要求,服务器获取哀告。

如浏览器UEnclaveL为:127.0.0.1/postAuth.html,

那正是说服务器获取到的伸手为:GET  /postAuth.html  HTTP/1.1

情趣是亟需根目录下postAuth.html文件的剧情,通过GET方法,使用HTTP/1.1商业事务(1.1是HTTP的版本号卡塔尔(قطر‎。这是服务器将剖判文件名,获知postAuth.html是叁个HTML文件,所以将”text/html”发送给浏览器,然后读取postAuth.html内容发给浏览器。

实现轻松的MIME类型识别代码如下:

要害就是经过文件后缀获取文件类型。

static void get_filetype(const char *filename, char *filetype)   
{  
    if (strstr(filename, ".html"))  
        strcpy(filetype, "text/html");  
    else if (strstr(filename, ".gif"))  
        strcpy(filetype, "image/gif");  
    else if (strstr(filename, ".jpg"))  
        strcpy(filetype, "image/jpeg");  
    else if (strstr(filename, ".png"))  
        strcpy(filetype, "image/png");  
    else  
    strcpy(filetype, "text/plain");  
}

若是援助HTTPS的话,那么咱们就#define HTTPS,那根本透过gcc 的D选项落成的,具体细节可参照man手册。

静态内容突显实现如下:

static void serve_static(int fd, char *filename, int filesize) 
{
    int srcfd;
    char *srcp, filetype[MAXLINE], buf[MAXBUF];

    /* Send response headers to client */
    get_filetype(filename, filetype);
    sprintf(buf, "HTTP/1.0 200 OKrn");
    sprintf(buf, "%sServer: Tiny Web Serverrn", buf);
    sprintf(buf, "%sContent-length: %drn", buf, filesize);
    sprintf(buf, "%sContent-type: %srnrn", buf, filetype);

    /* Send response body to client */
    srcfd = Open(filename, O_RDONLY, 0);
    srcp = Mmap(0, filesize, PROT_READ, MAP_PRIVATE, srcfd, 0);
    Close(srcfd);

    #ifdef HTTPS 
    if(ishttps)
    {
        SSL_write(ssl, buf, strlen(buf));
    SSL_write(ssl, srcp, filesize);
    }
    else
    #endif
    {
    Rio_writen(fd, buf, strlen(buf));
    Rio_writen(fd, srcp, filesize);
    }
    Munmap(srcp, filesize);
}

#3.CGI规范

假使不能不突显页面那么可相信贫乏动态人机联作本事,于是CGI产生了。CGI是公家网关接口(Common Gateway Interface卡塔尔,是在CGI程序和Web服务器之间传递音信的准绳。CGI允许Web服务器实行外界程序,并将它们的输出发送给浏览器。那样就提供了动态交互作用技术。

那便是说服务器是如何分开管理静态页面和动态CGI程序的啊?那关键是由此深入分析U福睿斯L的秘技。大家能够定义CGI程序的目录,如cgi-bin,那么只要UEscortL包括”cgi-bin”字符串则这是动态程序,且将U奥迪Q3L的参数给cgiargs。倘使是静态页面,parse_uri再次来到1,反正再次来到0。所以大家可以通过再次来到值分裂不一样的服务类型。

切切实实拆解剖判U奥迪Q3L情势如下:

static void serve_static(int fd, char *filename, int filesize) 
{
    int srcfd;
    char *srcp, filetype[MAXLINE], buf[MAXBUF];

    /* Send response headers to client */
    get_filetype(filename, filetype);
    sprintf(buf, "HTTP/1.0 200 OKrn");
    sprintf(buf, "%sServer: Tiny Web Serverrn", buf);
    sprintf(buf, "%sContent-length: %drn", buf, filesize);
    sprintf(buf, "%sContent-type: %srnrn", buf, filetype);

    /* Send response body to client */
    srcfd = Open(filename, O_RDONLY, 0);
    srcp = Mmap(0, filesize, PROT_READ, MAP_PRIVATE, srcfd, 0);
    Close(srcfd);

    #ifdef HTTPS 
    if(ishttps)
    {
        SSL_write(ssl, buf, strlen(buf));
    SSL_write(ssl, srcp, filesize);
    }
    else
    #endif
    {
    Rio_writen(fd, buf, strlen(buf));
    Rio_writen(fd, srcp, filesize);
    }
    Munmap(srcp, filesize);
}

GET格局的CGI标准落到实处原理:

服务器通过U牧马人L获取传给CGI程序的参数,设置情状变量QUEEnclaveY_ST陆风X8ING,并将规范输出重定向到文件描述符,然后通过EXEC函数簇推行外界CGI程序。外界CGI程序获取QUERAV4Y_STWranglerING并拍卖,管理完后输出结果。由于这时候正规输出已重定向到文件描述符,即发送给了浏览器。

福如东海细节如下:由于涉及到HTTPS,所以有个别有一点复杂。

static void serve_static(int fd, char *filename, int filesize) 
{
    int srcfd;
    char *srcp, filetype[MAXLINE], buf[MAXBUF];

    /* Send response headers to client */
    get_filetype(filename, filetype);
    sprintf(buf, "HTTP/1.0 200 OKrn");
    sprintf(buf, "%sServer: Tiny Web Serverrn", buf);
    sprintf(buf, "%sContent-length: %drn", buf, filesize);
    sprintf(buf, "%sContent-type: %srnrn", buf, filetype);

    /* Send response body to client */
    srcfd = Open(filename, O_RDONLY, 0);
    srcp = Mmap(0, filesize, PROT_READ, MAP_PRIVATE, srcfd, 0);
    Close(srcfd);

    #ifdef HTTPS 
    if(ishttps)
    {
        SSL_write(ssl, buf, strlen(buf));
    SSL_write(ssl, srcp, filesize);
    }
    else
    #endif
    {
    Rio_writen(fd, buf, strlen(buf));
    Rio_writen(fd, srcp, filesize);
    }
    Munmap(srcp, filesize);
}

POST格局的CGI规范落到实处原理:

鉴于POST格局不是经过UGL450L传递参数,所以实现情势与GET形式不均等。

POST格局获取浏览器发送过来的参数长度设置为条件变量CONTENT-LENGTH。并将参数重定向到CGI的科公输盘入,那重大通过pipe管道完结的。CGI程序从正式输入读取CONTENT-LENGTH个字符就收获了浏览器传送的参数,并将管理结果输出到正规输出,同理规范输出已重定向到文件描述符,所以浏览器就能够选用途理的响应。

切实贯彻细节如下:

static void serve_static(int fd, char *filename, int filesize) 
{
    int srcfd;
    char *srcp, filetype[MAXLINE], buf[MAXBUF];

    /* Send response headers to client */
    get_filetype(filename, filetype);
    sprintf(buf, "HTTP/1.0 200 OKrn");
    sprintf(buf, "%sServer: Tiny Web Serverrn", buf);
    sprintf(buf, "%sContent-length: %drn", buf, filesize);
    sprintf(buf, "%sContent-type: %srnrn", buf, filetype);

    /* Send response body to client */
    srcfd = Open(filename, O_RDONLY, 0);
    srcp = Mmap(0, filesize, PROT_READ, MAP_PRIVATE, srcfd, 0);
    Close(srcfd);

    #ifdef HTTPS 
    if(ishttps)
    {
        SSL_write(ssl, buf, strlen(buf));
    SSL_write(ssl, srcp, filesize);
    }
    else
    #endif
    {
    Rio_writen(fd, buf, strlen(buf));
    Rio_writen(fd, srcp, filesize);
    }
    Munmap(srcp, filesize);
}

目录展现效果原理:

珍视是经过U瑞虎L获取所需目录,然后拿走该目录下具备文件,并发送相应消息,包蕴文件格式对应图片,文件名,文件大小,最后改正时间等。由于大家发送的文书名是通过超链接的款式,所以大家能够点击文件名接续浏览新闻。

具体完毕细节如下:

static void serve_static(int fd, char *filename, int filesize) 
{
    int srcfd;
    char *srcp, filetype[MAXLINE], buf[MAXBUF];

    /* Send response headers to client */
    get_filetype(filename, filetype);
    sprintf(buf, "HTTP/1.0 200 OKrn");
    sprintf(buf, "%sServer: Tiny Web Serverrn", buf);
    sprintf(buf, "%sContent-length: %drn", buf, filesize);
    sprintf(buf, "%sContent-type: %srnrn", buf, filetype);

    /* Send response body to client */
    srcfd = Open(filename, O_RDONLY, 0);
    srcp = Mmap(0, filesize, PROT_READ, MAP_PRIVATE, srcfd, 0);
    Close(srcfd);

    #ifdef HTTPS 
    if(ishttps)
    {
        SSL_write(ssl, buf, strlen(buf));
    SSL_write(ssl, srcp, filesize);
    }
    else
    #endif
    {
    Rio_writen(fd, buf, strlen(buf));
    Rio_writen(fd, srcp, filesize);
    }
    Munmap(srcp, filesize);
}

HTTPS的实现:

HTTPS重要根据openssl的开源库达成。若无安装,那么大家就不#define HTTPS。
HTTPS的法力主要就是提供安全的连接,服务器和浏览器之间传递的数目是通过加密的,加密办法能够友善选定。

开端三翻五次时,服务器必要发送CA,由于大家的CA是友好签发的,所以须要大家友好增加为可靠。

访谈调控作用:

主假如通过获取客商端IP地址,并转移为整数,与上配置文件中定义的掩码,假若符合配置文件中允许的网段,那么能够访谈,不然无法。

切实落实如下。

static void serve_static(int fd, char *filename, int filesize) 
{
    int srcfd;
    char *srcp, filetype[MAXLINE], buf[MAXBUF];

    /* Send response headers to client */
    get_filetype(filename, filetype);
    sprintf(buf, "HTTP/1.0 200 OKrn");
    sprintf(buf, "%sServer: Tiny Web Serverrn", buf);
    sprintf(buf, "%sContent-length: %drn", buf, filesize);
    sprintf(buf, "%sContent-type: %srnrn", buf, filetype);

    /* Send response body to client */
    srcfd = Open(filename, O_RDONLY, 0);
    srcp = Mmap(0, filesize, PROT_READ, MAP_PRIVATE, srcfd, 0);
    Close(srcfd);

    #ifdef HTTPS 
    if(ishttps)
    {
        SSL_write(ssl, buf, strlen(buf));
    SSL_write(ssl, srcp, filesize);
    }
    else
    #endif
    {
    Rio_writen(fd, buf, strlen(buf));
    Rio_writen(fd, srcp, filesize);
    }
    Munmap(srcp, filesize);
}

构造文件的读取:

重视筛选音讯都定义与陈设文件中。

格式比方如下;

#HTTP PORT
PORT = 8888

故此读取配置文件函数具体如下:

static char* getconfig(char* name)  
{  
/* 
pointer meaning: 

...port...=...8000... 
   |  |   |   |  | 
  *fs |   |   |  *be    f->forward  b-> back 
      *fe |   *bs       s->start    e-> end 
          *equal 
*/  
    static char info[64];  
    int find=0;  
    char tmp[256],fore[64],back[64],tmpcwd[MAXLINE];  
    char *fs,*fe,*equal,*bs,*be,*start;  

    strcpy(tmpcwd,cwd);  
    strcat(tmpcwd,"/");  
    FILE *fp=getfp(strcat(tmpcwd,"config.ini"));  
    while(fgets(tmp,255,fp)!=NULL)  
    {  
        start=tmp;  
        equal=strchr(tmp,'=');  

        while(isblank(*start))  
              start;  
        fs=start;  

        if(*fs=='#')  
            continue;  
        while(isalpha(*start))  
              start;  
        fe=start-1;  

        strncpy(fore,fs,fe-fs 1);  
        fore[fe-fs 1]='\0';  
        if(strcmp(fore,name)!=0)  
            continue;  
        find=1;  

        start=equal 1;  
        while(isblank(*start))  
              start;  
        bs=start;  

        while(!isblank(*start)&&*start!='n')  
              start;  
        be=start-1;  

        strncpy(back,bs,be-bs 1);  
        back[be-bs 1]='\0';  
        strcpy(info,back);  
        break;  
    }  
    if(find)  
        return info;  
    else  
        return NULL;  
}

3)POST与GET的区别

       以 GET方式收受的数目是有长度限定,而用 POST情势选择的数码是从未长度约束的。而且,以 GET方式发送数据,可以通过 U昂科雷L的款型来发送,但 POST格局发送的多少必要求透过 Form才到发送。

CGI程序示例 mathcgi.h :

 1 #include <stdio.h>
 2 #include <stdlib.h>
 3 
 4 void mymath(char *arg)
 5 {
 6     //data1=1000&data2=2000
 7     char *argv[3];
 8     int i = 0;
 9     char *start = arg;
10     while(*start){
11         if(*start == '='){
12             start  ;
13             argv[i  ] = start;
14             continue;
15         }
16         if(*start== '&'){
17             *start = '\0';
18         }
19         start  ;
20     }
21     argv[i] = NULL;
22     int data1 = atoi(argv[0]);
23     int data2 = atoi(argv[1]);
24     printf("<html><body><h1>");
25     printf("%d   %d = %d<br/>", data1, data2, data1   data2);
26     printf("%d - %d = %d<br/>", data1, data2, data1 - data2);
27     printf("%d * %d = %d<br/>", data1, data2, data1 * data2);
28     printf("%d / %d = %d<br/>", data1, data2, data2==0? 0 : data1 / data2);
29     printf("%d %% %d = %d<br/>", data1, data2, data2==0? 0 : data1 % data2);
30     printf("</h1></body></html>");
31 }
32 
33 int main()
34 {
35     char *method = NULL;
36     char *query_string = NULL;
37     char *string_arg = NULL;
38     int content_len = -1;
39     char buf[1024];
40     if((method=getenv("METHOD"))){
41         if(strcasecmp(method, "GET") == 0){
42             if((query_string=getenv("QUERY_STRING"))){
43                 string_arg = query_string;
44             }
45         }else{
46             if(getenv("CONTENT_LENGTH")){
47                 content_len = atoi(getenv("CONTENT_LENGTH"));
48                 int i = 0;
49                 for(; i < content_len; i  ){
50                     read(0, &buf[i], 1);
51                 }
52                 buf[i] = '\0';
53                 string_arg = buf;
54             }
55         }
56     }
57 
58     mymath(string_arg);
59     return 0;
60 }

 (2)HTML

本项目中只是利用了黄金年代部分着力的HTML知识,上边是粗略的 index.html :

 1 <html>
 2     <head>hello http</head>
 3     <body>
 4         <h1>Hello My Web!</h1>
 5         <img src="imag/mgh.jpg" alt="default" width="100" height="100">
 6         <a href="cgi-bin/select_cgi">select</a>
 7         <!--<form action="/cgi-bin/math_cgi" method="POST">
 8         First data:<br>
 9         <input type="text" name="data1" value="0">
10         <br>
11         second data:<br>
12         <input type="text" name="data2" value="1">
13         <br><br>
14         <input type="submit" value="Submit">
15         </form>--!>
16     </body>
17 </html>

到那边就着力得以访谈网页音讯了:

4、本机进行环回测验,用的IP是127.0.0.1,Http左券的TCP连接暗中认可端口号为80:

betway必威 14

 图片自个儿选取,此页面完毕的是七个数的加减乘除,当点击submit时跳转页面如下:

betway必威 15

那会儿跳转到cgi_bin目录下的可施行文件debug_cgi,显示加减乘除的结果。

一个简陋的http服务器就到位了。前边还索要有些别的的扩张,再立异……

使用 POST 方法传递消息

多个更可信赖的向 CGI 程序传递消息的不二等秘书籍是 POST 方法。这种办法打包音讯的方式与 GET 方法少年老成致,不一样的是,它不是把新闻以文本字符串格局放在 UENVISIONL 中的 ? 之后进展传递,而是把它以单身的音讯方式张开传递。该新闻是以正规化输入的格局传给 CGI 脚本的。

咱俩生龙活虎致利用 cpp_get.cgi 程序来拍卖 POST 方法。让我们以相似的例子,通过行使 HTML 表单和交给开关来传递八个值,只然而此番大家利用的不是 GET 方法,而是 POST 方法,如下所示:

<form action="/cgi-bin/cpp_get.cgi" method="post">
名:<input type="text" name="first_name"><br />
姓:<input type="text" name="last_name" />

<input type="submit" value="提交" />
</form>

3、相关本事解释:

(1)CGI:通用网关接口

  基本原理:通用网关接口是叁个Web服务器主机提供音信服务的标准接口。通过CGI接口,Web服务器根据客商端提交的财富央浼音信,转交给劳务器端对应的CGI程序开展拍卖,最终回来结果给客商端。轻松的话便是HTTP服务器与客商端实行“交谈”的后生可畏种工具,其程序须运维在互连网服务器上。

  组成CGI通讯系统的是两局地:生龙活虎部分是html页面,就是在客户端浏览器上显得的页面。另风流浪漫部分则是运转在服务器上的Cgi程序。绝大好多的CGI程序被用来讲授管理来自表单的输入音信,并在服务器发生相应的管理,或将相应的新闻反映给浏览器。CGI程序使网页具备人机联作功效。

  CGI在客商端与服务器通信中的管理步骤:

  1)通过Internet把客户央浼送到服务器;

  2)服务器收到客商央浼并付出相应CGI程序处理;

  3)CGI程序把管理结果传送给服务器;

  4)服务器把结果重返给客商。

  前面已经介绍过服务器和客户端之间的通讯,实际上是客商端的浏览器和劳务器端的http服务器之间的HTTP通讯,我们只供给知道浏览器央求施行服务器上哪些CGI程序就可以了,其余不必钻探细节,因为那些经过无需程序猿去操作。服务器和CGI程序之间的简报才是大家关心的。通常情状下,服务器和CGI程序之间是通过标准输入输出来张开数量传递的,而以此进度需求情状变量的搭档方可达成。在服务器端实行步骤:1)服务器将U普拉多L指向一个应用程序  2)服务器为应用程序施行做筹划  3)应用程序试行,读取规范输入和有关景况变量  4)应用程序实行正规化输出。

(2)CGI关于境况变量

对此CGI程序来讲,它三回九转了系统的蒙受变量。CGI景况变量在CGI程序运行时带头化,在终结时销毁。

       当二个CGI程序不是被HTTP服务器调用时,它的际遇变量差不离是系统碰到变量的复制。

当以此CGI程序被HTTP服务器调用时,它的碰着变量就能够多了以下关于HTTP服务器、客商端、CGI传输进度等门类。

betway必威 16

CONTENT_TYPE:如application/x-www-form-urlencoded,表示数据出自HTML表单,并且通过了U兰德LacrosseL编码。

ACCEPT:客商机所帮衬的MIME类型清单,内容如:”image/gif,image/jpeg”

REQUEST_METHOD:本项目事关多如牛毛的三种方法:POST和GET,但大家写CGI程序时,最后还要思谋任何的情景。

  境况变量是贰个封存客商音讯的内部存储器区。当顾客端的客商通过浏览器发出CGI必要时,服务器就找出本地的应和CGI程序并试行它。在实践CGI程序的同一时候,服务器把该客户的消息保存到碰着变量里。接下来,CGI程序的推行流程是这么的:查询与该CGI程序进程相应的景况变量:第一步是request_method,即便是POST,就从境况变量的len,然后到该进度相应的正经八百输入抽取len长的多寡。固然是GET,则客商数据就在处境变量的QUELX570Y_STRING里。

 (3)POST/GET传输形式详细明白

什么是 CGI?

集体网关接口(CGI),是风姿浪漫套规范,定义了音信是怎么着在 Web 服务器和客商端脚本之间实行调换的。

CGI 标准方今是由 NCSA 维护的,NCSA 定义 CGI 如下:

  • 公共网关接口(CGI),是风华正茂种用于外界网关程序与新闻服务器(如 HTTP 服务器)对接的接口标准。
  • 时下的版本是 CGI/1.1,CGI/1.2 版本正在推动中。

5、蒙受的生龙活虎对标题:

1)当草石蚕回测量检验ok,Linux下的浏览器测验也足以,但无法接外界的浏览器访问(未有设置桥接方式)嗯~即使在表面浏览器测量试验的话千万别忘记关闭防火墙。

不留余地:切换一流客商:$service iptables stop

2)服务器应答时,未有将html格式的页面发送,而是将底层的落到实处代码显示在浏览器,而且在调度时将自然要打字与印刷的调节和测量试验消息会打字与印刷到网页上(在回复空行时将send期待发送的数值写的太大,本来只要求发送八个字节的故事情节)
缓慢解决:先检查代码,思路正确,在轻便并发难点的地点投入调试新闻,最终将标题一定在echo_www()函数内 。

3)不可能显示图片(这么些标题是绝非将全数发送的情况考虑全盘,只构思到目录、可执路程序,但从不考虑到借使央求的是二个路径鲜明的习以为常文书)
减轻:测验伏乞一个路径明显的test.html文件,参与调节和测验消息,将难题一定在:借使央求的能源存在,应该什么管理。对于普通文书,找到后并回显给浏览器;假若是目录,应答的是暗中认可页面;假如是可执路程序,实行后回来结果

4)能展现图片后,但显得的不完全(原因:echo_www中,期待读取意气风发行消息的line值太小,不可能存下一张图纸)

5)运维cgi方式时,每回提交数据并开展submit后都会活动出现提醒下载的页面
缘由:在响应报头中,将Content-Type中的”text”写成”test”。而浏览器对于不能够辨识或深入分析的实体,都会唤醒客商下载。

 

向 CGI 程序传递下拉框数据

当有几个选择可用,但只好选取七个或三个选项时,我们采用下拉框。

上面包车型地铁 HTML 代码实例是贰个包括下拉框的表单:

<form action="/cgi-bin/cpp_dropdown.cgi" 
                       method="post" target="_blank">
<select name="dropdown">
<option value="Maths" selected>数学</option>
<option value="Physics">物理</option>
</select>
<input type="submit" value="提交"/>
</form>

下边的 C 程序会生成 cpp_dropdown.cgi 脚本,用于拍卖 Web 浏览器通过下拉框给出的输入。

#include <iostream>
#include <vector>  
#include <string>  
#include <stdio.h>  
#include <stdlib.h> 

#include <cgicc/CgiDefs.h> 
#include <cgicc/Cgicc.h> 
#include <cgicc/HTTPHTMLHeader.h> 
#include <cgicc/HTMLClasses.h> 

using namespace std;
using namespace cgicc;

int main ()
{
   Cgicc formData;

   cout << "Content-type:text/htmlrnrn";
   cout << "<html>n";
   cout << "<head>n";
   cout << "<title>向 CGI 程序传递下拉框数据</title>n";
   cout << "</head>n";
   cout << "<body>n";

   form_iterator fi = formData.getElement("dropdown");  
   if( !fi->isEmpty() && fi != (*formData).end()) {  
      cout << "Value Selected: " << **fi << endl;  
   }

   cout << "<br/>n";
   cout << "</body>n";
   cout << "</html>n";

   return 0;
}

2)GET方法

  在该办法下,CGI程序不可能直接从服务器的正式输入(用户发送的音讯正文)中获取数据,因为服务器把它从行业内部输入采用到得数据编码到情状变量QUESportageY_STRING(或PATH_INFO)。

  选择GET方法提交HTML表单数据的时候,顾客机将把这几个多少附加到由ACTION标志命名的U奥迪Q5L的结尾,用八个总结把经过U福睿斯L编码后的新闻与CGI程序的名字分别:?name=hgq$id=1,QUERY_ST福睿斯ING的值为name=hgq&id=1(?左边为要央求的能源,左侧为参数,参数情势经常为name=value方式,以“&”连接)。恐怕使用nomal格局的GET方法,无参数,不带正文,唯有央求行 音信报头 空行。有个别程序猿不愿意利用GET方法,因为在他们看来,把动态新闻附加在U奥迪Q5L的末梢有违URubiconL的角度:U宝马X5L作为风华正茂种标准用语,通常是用作互连网资源的独步天下定位标示。

向 CGI 程序传递复选框数据

当须要选用五个采纳时,大家运用复选框。

上面包车型地铁 HTML 代码实例是二个分包四个复选框的表单:

<form action="/cgi-bin/cpp_checkbox.cgi" 
         method="POST" 
         target="_blank">
<input type="checkbox" name="maths" value="on" /> 数学
<input type="checkbox" name="physics" value="on" /> 物理
<input type="submit" value="选择学科" />
</form>

上边包车型地铁 C 程序会生成 cpp_checkbox.cgi 脚本,用于拍卖 Web 浏览器通过复选框给出的输入。

#include <iostream>
#include <vector>  
#include <string>  
#include <stdio.h>  
#include <stdlib.h> 

#include <cgicc/CgiDefs.h> 
#include <cgicc/Cgicc.h> 
#include <cgicc/HTTPHTMLHeader.h> 
#include <cgicc/HTMLClasses.h> 

using namespace std;
using namespace cgicc;

int main ()
{
   Cgicc formData;
   bool maths_flag, physics_flag;

   cout << "Content-type:text/htmlrnrn";
   cout << "<html>n";
   cout << "<head>n";
   cout << "<title>向 CGI 程序传递复选框数据</title>n";
   cout << "</head>n";
   cout << "<body>n";

   maths_flag = formData.queryCheckbox("maths");
   if( maths_flag ) {  
      cout << "Maths Flag: ON " << endl;  
   }else{
      cout << "Maths Flag: OFF " << endl;  
   }
   cout << "<br/>n";

   physics_flag = formData.queryCheckbox("physics");
   if( physics_flag ) {  
      cout << "Physics Flag: ON " << endl;  
   }else{
      cout << "Physics Flag: OFF " << endl;  
   }
   cout << "<br/>n";
   cout << "</body>n";
   cout << "</html>n";

   return 0;
}

简单的 URL 实例:Get 方法

下边是二个简易的 UEscortL,使用 GET 方法传递四个值给 hello_get.py 程序。

/cgi-bin/cpp_get.cgi?first_name=ZARA&last_name=ALI

下边包车型客车实例生成 cpp_get.cgi CGI 程序,用于拍卖 Web 浏览器给出的输入。通过应用 C CGI 库,能够十分轻松地会见传递的音信:

#include <iostream>
#include <vector>  
#include <string>  
#include <stdio.h>  
#include <stdlib.h> 

#include <cgicc/CgiDefs.h> 
#include <cgicc/Cgicc.h> 
#include <cgicc/HTTPHTMLHeader.h> 
#include <cgicc/HTMLClasses.h>  

using namespace std;
using namespace cgicc;

int main ()
{
   Cgicc formData;

   cout << "Content-type:text/htmlrnrn";
   cout << "<html>n";
   cout << "<head>n";
   cout << "<title>使用 GET 和 POST 方法</title>n";
   cout << "</head>n";
   cout << "<body>n";

   form_iterator fi = formData.getElement("first_name");  
   if( !fi->isEmpty() && fi != (*formData).end()) {  
      cout << "名:" << **fi << endl;  
   }else{
      cout << "No text entered for first name" << endl;  
   }
   cout << "<br/>n";
   fi = formData.getElement("last_name");  
   if( !fi->isEmpty() &&fi != (*formData).end()) {  
      cout << "姓:" << **fi << endl;  
   }else{
      cout << "No text entered for last name" << endl;  
   }
   cout << "<br/>n";

   cout << "</body>n";
   cout << "</html>n";

   return 0;
}

今后,编写翻译上边的次第,如下所示:

$g   -o cpp_get.cgi cpp_get.cpp -lcgicc

生成 cpp_get.cgi,并把它座落 CGI 目录中,并尝试利用下边包车型客车链接实行拜会:

/cgi-bin/cpp_get.cgi?first_name=ZARA&last_name=ALI

那会时有爆发以下结果:

名:ZARA 
姓:ALI 

本文由betway必威发布于网络技术,转载请注明出处:betway必威:目录显示等

TAG标签: betway必威
Ctrl+D 将本页面保存为书签,全面了解最新资讯,方便快捷。