日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

tinyhttpd-0.1.0_hacking

發(fā)布時(shí)間:2025/6/15 编程问答 15 豆豆
生活随笔 收集整理的這篇文章主要介紹了 tinyhttpd-0.1.0_hacking 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
1 /**************************************************************************** 2 * 3 * tinyhttpd-0.1.0_hacking 4 * 5 * 1.這是tinyhttpd-0.1.0版本中httpd.c(主程序)的源碼,源碼不到500行(除去注釋). 6 * 2.通過分析、閱讀該源碼,可以一窺web服務(wù)器的大致工作機(jī)制. 7 * 3.知識(shí)量: 8 * 1.C語言; 9 * 2.Unix或類Unix系統(tǒng)編程; 10 * 3.微量的http協(xié)議(請(qǐng)求行、消息頭、實(shí)體內(nèi)容); 11 * 4.如何閱讀別人的代碼( 從main函數(shù)開始 :) ); 12 * 4.tinyhttpd-0.1.0 文件結(jié)構(gòu)如下: 13 * . 14 * |-- Makefile -------->makefile 文件 15 * |-- README -------->說明文檔 16 * |-- htdocs -------->程序會(huì)到該文件夾下找對(duì)應(yīng)html、cgi文件 17 * | |-- README -------->說明文檔 18 * | |-- check.cgi -------->cgi 程序 19 * | |-- color.cgi ----^ 20 * | `-- index.html -------->默認(rèn)的 web 首頁文件 21 * |-- httpd.c -------->你接下來要閱讀的文件 22 * `-- simpleclient.c -------->沒發(fā)現(xiàn)該文件有任何用處 @_@ 23 * 5.如何閱讀該文檔: 24 * 1.linux下使用vi/vim配和ctags,windows下使用Source Insight,當(dāng)然你也 25 * 可以用其他文本編輯器看. 26 * 2.先找到main函數(shù),然后就可以開始閱讀了,遇到對(duì)應(yīng)的函數(shù),就去看對(duì)應(yīng)的 27 * 函數(shù). 28 * 3.對(duì)于有些函數(shù),本人沒有添加注釋,或者說本人覺得沒必要. 29 * 4.祝您好運(yùn). :) 30 * 31 * 6.tinyhttpd-0.1.0版本下載url: http://sourceforge.net/projects/tinyhttpd/ 32 * 33 * 如果您對(duì)本文有任何意見、提議,可以發(fā)郵件至zengjf42@163.com,會(huì)盡快回復(fù). 34 * 本文的最終解釋權(quán)歸本人(曾劍鋒)所有,僅供學(xué)習(xí)、討論. 35 * 36 * 2015-3-1 陰 深圳 尚觀 Var 37 * 38 ***************************************************************************/ 39 40 41 /* J. David's webserver */ 42 /* This is a simple webserver. 43 * Created November 1999 by J. David Blackstone. 44 * CSE 4344 (Network concepts), Prof. Zeigler 45 * University of Texas at Arlington 46 */ 47 /* This program compiles for Sparc Solaris 2.6. 48 * To compile for Linux: 49 * 1) Comment out the #include <pthread.h> line. 50 * 2) Comment out the line that defines the variable newthread. 51 * 3) Comment out the two lines that run pthread_create(). 52 * 4) Uncomment the line that runs accept_request(). 53 * 5) Remove -lsocket from the Makefile. 54 */ 55 #include <stdio.h> 56 #include <sys/socket.h> 57 #include <sys/types.h> 58 #include <netinet/in.h> 59 #include <arpa/inet.h> 60 #include <unistd.h> 61 #include <ctype.h> 62 #include <strings.h> 63 #include <string.h> 64 #include <sys/stat.h> 65 #include <pthread.h> 66 #include <sys/wait.h> 67 #include <stdlib.h> 68 69 #define ISspace(x) isspace((int)(x)) 70 71 #define SERVER_STRING "Server: jdbhttpd/0.1.0\r\n" 72 73 void accept_request(int); 74 void bad_request(int); 75 void cat(int, FILE *); 76 void cannot_execute(int); 77 void error_die(const char *); 78 void execute_cgi(int, const char *, const char *, const char *); 79 int get_line(int, char *, int); 80 void headers(int, const char *); 81 void not_found(int); 82 void serve_file(int, const char *); 83 int startup(u_short *); 84 void unimplemented(int); 85 86 /** 87 * accept_request 函數(shù)說明: 88 * 1.獲取請(qǐng)求方式,目前只支持GET、POST請(qǐng)求; 89 * 2.在本程序中所有的POST請(qǐng)求、帶參數(shù)的GET請(qǐng)求都都被定義為訪問cgi程序; 90 * 3.從帶參數(shù)的GET請(qǐng)求中分離出請(qǐng)求參數(shù); 91 * 4.如果沒有指定需要訪問的文件,使用index.html文件作為默認(rèn)訪問文件; 92 * 5.檢查需要訪問的文件是否存在,以及其是否具有對(duì)應(yīng)的權(quán)限; 93 * 6.根據(jù)是否是cgi程序訪問,來執(zhí)行對(duì)應(yīng)的任務(wù). 94 */ 95 void accept_request(int client) 96 { 97 /** 98 * 局部變量說明: 99 * 1.buf : buffer縮寫,主要用于暫存從socket中讀出來的數(shù)據(jù); 100 * 2.numchars : 用于保存每次從socket中讀到的字符的個(gè)數(shù); 101 * 3.method : 用于保存請(qǐng)求方式,目前該軟件只支持GET、POST這兩種方式; 102 * 4.url : 用于保存訪問文件信息,有些地方叫uri; 103 * 5.path : 用于保存文件路徑; 104 * 6.i, j : 處理數(shù)據(jù)時(shí)的下標(biāo); 105 * 7.st : 在判斷文件類型、是否存在的時(shí)候用到; 106 * 8.cgi : 是否調(diào)用cgi程序的標(biāo)志. 107 */ 108 char buf[1024]; 109 int numchars; 110 char method[255]; 111 char url[255]; 112 char path[512]; 113 size_t i, j; 114 struct stat st; 115 int cgi = 0; /* becomes true if server decides this is a CGI 116 * program */ 117 char *query_string = NULL; 118 119 /** 120 * 判斷程序是否是GET、POST請(qǐng)求兩種的其中一種,如果不是則報(bào)錯(cuò). 121 */ 122 numchars = get_line(client, buf, sizeof(buf)); 123 i = 0; j = 0; 124 while (!ISspace(buf[j]) && (i < sizeof(method) - 1)) 125 { 126 method[i] = buf[j]; 127 i++; j++; 128 } 129 method[i] = '\0'; 130 131 if (strcasecmp(method, "GET") && strcasecmp(method, "POST")) 132 { 133 unimplemented(client); 134 return; 135 } 136 137 /** 138 * 該程序把POST請(qǐng)求定義為cgi請(qǐng)求. 139 */ 140 if (strcasecmp(method, "POST") == 0) 141 cgi = 1; 142 143 /** 144 * 獲取當(dāng)前url,這里的url不過括網(wǎng)址,而是除去網(wǎng)址之后的東西, 145 * 如瀏覽器中輸入:http://127.0.0.1:8080/example/index.html 146 * 得到的url:/example/index.html 147 * 在有些地方不稱這個(gè)為url,稱之為uri 148 */ 149 i = 0; 150 while (ISspace(buf[j]) && (j < sizeof(buf))) 151 j++; 152 while (!ISspace(buf[j]) && (i < sizeof(url) - 1) && (j < sizeof(buf))) 153 { 154 url[i] = buf[j]; 155 i++; j++; 156 } 157 url[i] = '\0'; 158 159 /** 160 * 每次運(yùn)行的時(shí)候都會(huì)出現(xiàn)2次這個(gè),目前還不知道是什么原因?qū)е碌脑? 161 * 這是本人在源代碼的基礎(chǔ)上添加的調(diào)試輸出. 162 * url: /favicon.ico 163 * url: /favicon.ico 164 */ 165 printf("url: %s\n", url); 166 167 /** 168 * 如果是GET請(qǐng)求,如果帶了請(qǐng)求參數(shù),那么也是cgi請(qǐng)求,并且從url中分離出請(qǐng)求參數(shù) 169 */ 170 if (strcasecmp(method, "GET") == 0) 171 { 172 query_string = url; 173 while ((*query_string != '?') && (*query_string != '\0')) 174 query_string++; 175 if (*query_string == '?') 176 { 177 cgi = 1; 178 *query_string = '\0'; 179 query_string++; 180 } 181 } 182 183 /** 184 * 所有的需要的html文件、cgi程序都在htdocs文件夾中, 185 * 如果沒有指定html文件,或者cgi程序,那么使用默認(rèn)的index.html文件 186 * 作為目標(biāo)輸出文件. 187 */ 188 sprintf(path, "htdocs%s", url); 189 if (path[strlen(path) - 1] == '/') 190 strcat(path, "index.html"); 191 192 /** 193 * 檢查要訪問的文件的狀態(tài),如: 194 * 1.是否存在; 195 * 2.是否是一個(gè)文件夾; 196 * 3.如果是cgi程序,是否用于對(duì)應(yīng)的權(quán)限. 197 * 當(dāng)然如果執(zhí)行stat時(shí)就出錯(cuò)了,那么,直接將socket中的數(shù)據(jù)讀完, 198 * 然后返回沒有找到相關(guān)內(nèi)容的信息提示. 199 */ 200 if (stat(path, &st) == -1) { 201 while ((numchars > 0) && strcmp("\n", buf)) /* read & discard headers */ 202 numchars = get_line(client, buf, sizeof(buf)); 203 not_found(client); 204 } 205 else 206 { 207 if ((st.st_mode & S_IFMT) == S_IFDIR) /* 如果是一個(gè)文件夾 */ 208 strcat(path, "/index.html"); 209 if ((st.st_mode & S_IXUSR) || 210 (st.st_mode & S_IXGRP) || 211 (st.st_mode & S_IXOTH) ) /* 權(quán)限問題 */ 212 cgi = 1; 213 214 /** 215 * 通過cgi變量來判斷是執(zhí)行cgi程序,還是僅僅是返回一個(gè)html頁面. 216 */ 217 if (!cgi) 218 serve_file(client, path); /* 向客戶端返回一個(gè)html文件 */ 219 else 220 execute_cgi(client, path, method, query_string); /* 執(zhí)行一個(gè)cgi程序 */ 221 } 222 223 close(client); 224 } 225 226 void bad_request(int client) 227 { 228 char buf[1024]; 229 230 sprintf(buf, "HTTP/1.0 400 BAD REQUEST\r\n"); 231 send(client, buf, sizeof(buf), 0); 232 sprintf(buf, "Content-type: text/html\r\n"); 233 send(client, buf, sizeof(buf), 0); 234 sprintf(buf, "\r\n"); 235 send(client, buf, sizeof(buf), 0); 236 sprintf(buf, "<P>Your browser sent a bad request, "); 237 send(client, buf, sizeof(buf), 0); 238 sprintf(buf, "such as a POST without a Content-Length.\r\n"); 239 send(client, buf, sizeof(buf), 0); 240 } 241 242 /** 243 * 主要完成將resource指向的文件內(nèi)容拷貝輸出到客戶端瀏覽器中 244 */ 245 void cat(int client, FILE *resource) 246 { 247 char buf[1024]; 248 249 fgets(buf, sizeof(buf), resource); 250 while (!feof(resource)) 251 { 252 send(client, buf, strlen(buf), 0); 253 fgets(buf, sizeof(buf), resource); 254 } 255 } 256 257 void cannot_execute(int client) 258 { 259 char buf[1024]; 260 261 sprintf(buf, "HTTP/1.0 500 Internal Server Error\r\n"); 262 send(client, buf, strlen(buf), 0); 263 sprintf(buf, "Content-type: text/html\r\n"); 264 send(client, buf, strlen(buf), 0); 265 sprintf(buf, "\r\n"); 266 send(client, buf, strlen(buf), 0); 267 sprintf(buf, "<P>Error prohibited CGI execution.\r\n"); 268 send(client, buf, strlen(buf), 0); 269 } 270 271 void error_die(const char *sc) 272 { 273 perror(sc); 274 exit(1); 275 } 276 277 void execute_cgi(int client, const char *path, 278 const char *method, const char *query_string) 279 { 280 /** 281 * 局部變量說明: 282 * 1.buf : buffer縮寫; 283 * 2.cgi_output : 用于保存輸出管道的文件描述符; 284 * 3.cgi_input : 用于保存輸入管道的文件描述符; 285 * 4.pid : 進(jìn)程pid,最后父進(jìn)程退出之前,等待子進(jìn)程先退出, 286 * 并回收相關(guān)的資源,這部分工作主要由waitpid()來完成; 287 * 5.status : 在waitpid()中用于保存子進(jìn)程的退出狀態(tài),本程序沒有具體使用; 288 * 6.i : 計(jì)數(shù)器; 289 * 7.c : POST讀取請(qǐng)求參數(shù)時(shí),讀取到的字符保存在這里; 290 * 8.numchars : 讀取的字符個(gè)數(shù); 291 * 9.conten_length : 內(nèi)容實(shí)體的字符數(shù); 292 */ 293 char buf[1024]; 294 int cgi_output[2]; 295 int cgi_input[2]; 296 pid_t pid; 297 int status; 298 int i; 299 char c; 300 int numchars = 1; 301 int content_length = -1; 302 303 /** 304 * 在本程序中,GET請(qǐng)求的消息頭沒有任何用處,直接處理掉就行了, 305 * 而如果是POST請(qǐng)求,需要的消息頭中的獲取實(shí)體的大小,也就是Content-Length:后面跟的數(shù)字 306 */ 307 buf[0] = 'A'; buf[1] = '\0'; 308 if (strcasecmp(method, "GET") == 0) 309 while ((numchars > 0) && strcmp("\n", buf)) /* read & discard headers */ 310 numchars = get_line(client, buf, sizeof(buf)); 311 else /* POST */ 312 { 313 numchars = get_line(client, buf, sizeof(buf)); 314 while ((numchars > 0) && strcmp("\n", buf)) 315 { 316 buf[15] = '\0'; 317 if (strcasecmp(buf, "Content-Length:") == 0) 318 content_length = atoi(&(buf[16])); 319 numchars = get_line(client, buf, sizeof(buf)); 320 } 321 if (content_length == -1) { 322 bad_request(client); 323 return; 324 } 325 } 326 327 /** 328 * 返回返回行信息. 329 */ 330 sprintf(buf, "HTTP/1.0 200 OK\r\n"); 331 send(client, buf, strlen(buf), 0); 332 333 /** 334 * 父子進(jìn)程通過管道通信. 335 */ 336 if (pipe(cgi_output) < 0) { 337 cannot_execute(client); 338 return; 339 } 340 if (pipe(cgi_input) < 0) { 341 cannot_execute(client); 342 return; 343 } 344 345 /** 346 * 創(chuàng)建子進(jìn)程,用于執(zhí)行cgi程序,父進(jìn)程接受子進(jìn)程的結(jié)果,并返回給瀏覽器 347 */ 348 if ( (pid = fork()) < 0 ) { 349 cannot_execute(client); 350 return; 351 } 352 if (pid == 0) /* child: CGI script */ 353 { 354 char meth_env[255]; //cgi 請(qǐng)求方式環(huán)境變量 355 char query_env[255]; //cgi GET請(qǐng)求參數(shù)環(huán)境變量 356 char length_env[255]; //cgi POST請(qǐng)求參數(shù)內(nèi)容大小環(huán)境變量 357 358 /** 359 * 重定向標(biāo)準(zhǔn)輸入輸出,并設(shè)置好對(duì)應(yīng)的環(huán)境變量. 360 */ 361 dup2(cgi_output[1], 1); 362 dup2(cgi_input[0], 0); 363 close(cgi_output[0]); 364 close(cgi_input[1]); 365 sprintf(meth_env, "REQUEST_METHOD=%s", method); 366 putenv(meth_env); 367 if (strcasecmp(method, "GET") == 0) { 368 sprintf(query_env, "QUERY_STRING=%s", query_string); 369 putenv(query_env); 370 } 371 else { /* POST */ 372 sprintf(length_env, "CONTENT_LENGTH=%d", content_length); 373 putenv(length_env); 374 } 375 /* 執(zhí)行對(duì)應(yīng)的程序 */ 376 execl(path, path, NULL); 377 exit(0); 378 } else { /* parent */ 379 close(cgi_output[1]); 380 close(cgi_input[0]); 381 /** 382 * 對(duì)于POST請(qǐng)求,將實(shí)體中的請(qǐng)求參數(shù)通過管道傳送到cgi程序中 383 */ 384 if (strcasecmp(method, "POST") == 0) 385 for (i = 0; i < content_length; i++) { 386 recv(client, &c, 1, 0); 387 write(cgi_input[1], &c, 1); 388 } 389 /** 390 * 讀取cgi程序的執(zhí)行結(jié)果,返回給瀏覽器 391 */ 392 while (read(cgi_output[0], &c, 1) > 0) 393 send(client, &c, 1, 0); 394 395 close(cgi_output[0]); 396 close(cgi_input[1]); 397 /** 398 * 等待子進(jìn)程運(yùn)行結(jié)束,并回收子進(jìn)程的資源, 399 * 防止出現(xiàn)孤兒進(jìn)程 400 */ 401 waitpid(pid, &status, 0); 402 } 403 } 404 405 int get_line(int sock, char *buf, int size) 406 { 407 /** 408 * 局部變量說明: 409 * 1.i : 數(shù)組下標(biāo)計(jì)數(shù),不能大于size; 410 * 2.c : 每次讀到的字符保存在這里面; 411 * 3.n : 每次讀到的字符個(gè)數(shù). 412 */ 413 int i = 0; 414 char c = '\0'; 415 int n; 416 417 /** 418 * 一直讀到buf滿了,或者遇到了'\n'為止. 419 */ 420 while ((i < size - 1) && (c != '\n')) 421 { 422 n = recv(sock, &c, 1, 0); 423 /* DEBUG printf("%02X\n", c); */ 424 if (n > 0) 425 { 426 /** 427 * 讀到'\r'也算是結(jié)束,通過判斷后面有沒有跟'\n'來判斷是否要將下 428 * 一個(gè)字符取出來,并且無論'\r'后面跟不跟'\n',都將'\r'換成'\n'. 429 */ 430 if (c == '\r') 431 { 432 n = recv(sock, &c, 1, MSG_PEEK); 433 /* DEBUG printf("%02X\n", c); */ 434 if ((n > 0) && (c == '\n')) 435 recv(sock, &c, 1, 0); 436 else 437 c = '\n'; 438 } 439 buf[i] = c; 440 i++; 441 } 442 else 443 c = '\n'; 444 } 445 buf[i] = '\0'; /* 字符串結(jié)尾 */ 446 447 return(i); 448 } 449 450 void headers(int client, const char *filename) 451 { 452 char buf[1024]; 453 (void)filename; /* could use filename to determine file type */ 454 455 strcpy(buf, "HTTP/1.0 200 OK\r\n"); 456 send(client, buf, strlen(buf), 0); 457 strcpy(buf, SERVER_STRING); 458 send(client, buf, strlen(buf), 0); 459 sprintf(buf, "Content-Type: text/html\r\n"); 460 send(client, buf, strlen(buf), 0); 461 strcpy(buf, "\r\n"); 462 send(client, buf, strlen(buf), 0); 463 } 464 465 void not_found(int client) 466 { 467 char buf[1024]; 468 469 sprintf(buf, "HTTP/1.0 404 NOT FOUND\r\n"); 470 send(client, buf, strlen(buf), 0); 471 sprintf(buf, SERVER_STRING); 472 send(client, buf, strlen(buf), 0); 473 sprintf(buf, "Content-Type: text/html\r\n"); 474 send(client, buf, strlen(buf), 0); 475 sprintf(buf, "\r\n"); 476 send(client, buf, strlen(buf), 0); 477 sprintf(buf, "<HTML><TITLE>Not Found</TITLE>\r\n"); 478 send(client, buf, strlen(buf), 0); 479 sprintf(buf, "<BODY><P>The server could not fulfill\r\n"); 480 send(client, buf, strlen(buf), 0); 481 sprintf(buf, "your request because the resource specified\r\n"); 482 send(client, buf, strlen(buf), 0); 483 sprintf(buf, "is unavailable or nonexistent.\r\n"); 484 send(client, buf, strlen(buf), 0); 485 sprintf(buf, "</BODY></HTML>\r\n"); 486 send(client, buf, strlen(buf), 0); 487 } 488 489 void serve_file(int client, const char *filename) 490 { 491 /** 492 * 局部變量說明: 493 * 1.resource : 打開的文件的文件指針; 494 * 2.numchars : 每次讀到的字符個(gè)數(shù); 495 * 3.buf : buffer的縮寫. 496 */ 497 FILE *resource = NULL; 498 int numchars = 1; 499 char buf[1024]; 500 501 /** 502 * 在本程序中消息頭對(duì)于純GET請(qǐng)求沒有什么用,直接讀取丟掉. 503 */ 504 buf[0] = 'A'; buf[1] = '\0'; 505 while ((numchars > 0) && strcmp("\n", buf)) /* read & discard headers */ 506 numchars = get_line(client, buf, sizeof(buf)); 507 508 resource = fopen(filename, "r"); 509 if (resource == NULL) 510 not_found(client); 511 else 512 { 513 /* 發(fā)送消息頭 */ 514 headers(client, filename); 515 /* 發(fā)送內(nèi)容實(shí)體 */ 516 cat(client, resource); 517 } 518 fclose(resource); 519 } 520 521 /** 522 * startup 函數(shù)完成內(nèi)容: 523 * 1.獲取一個(gè)作為服務(wù)器的socket; 524 * 2.綁定服務(wù)器端的socket; 525 * 3.通過判斷參數(shù)port的值,確定是否需要?jiǎng)討B(tài)分配端口號(hào); 526 * 4.服務(wù)器開啟監(jiān)聽; 527 * 5.返回服務(wù)器段的socket文件描述符. 528 */ 529 int startup(u_short *port) 530 { 531 /** 532 * 局部變量說明: 533 * 1.httpd : 保存服務(wù)器socket描述符,并作為返回值返回; 534 * 2.name : 用于保存服務(wù)器本身的socket信息,創(chuàng)建服務(wù)器. 535 */ 536 int httpd = 0; 537 struct sockaddr_in name; 538 539 httpd = socket(PF_INET, SOCK_STREAM, 0); 540 if (httpd == -1) 541 error_die("socket"); 542 543 memset(&name, 0, sizeof(name)); 544 name.sin_family = AF_INET; 545 name.sin_port = htons(*port); 546 name.sin_addr.s_addr = htonl(INADDR_ANY); 547 548 if (bind(httpd, (struct sockaddr *)&name, sizeof(name)) < 0) 549 error_die("bind"); 550 551 if (*port == 0) /* if dynamically allocating a port */ 552 { 553 int namelen = sizeof(name); 554 if (getsockname(httpd, (struct sockaddr *)&name, &namelen) == -1) 555 error_die("getsockname"); 556 *port = ntohs(name.sin_port); 557 } 558 559 if (listen(httpd, 5) < 0) 560 error_die("listen"); 561 return(httpd); 562 } 563 564 void unimplemented(int client) 565 { 566 char buf[1024]; 567 568 sprintf(buf, "HTTP/1.0 501 Method Not Implemented\r\n"); 569 send(client, buf, strlen(buf), 0); 570 sprintf(buf, SERVER_STRING); 571 send(client, buf, strlen(buf), 0); 572 sprintf(buf, "Content-Type: text/html\r\n"); 573 send(client, buf, strlen(buf), 0); 574 sprintf(buf, "\r\n"); 575 send(client, buf, strlen(buf), 0); 576 sprintf(buf, "<HTML><HEAD><TITLE>Method Not Implemented\r\n"); 577 send(client, buf, strlen(buf), 0); 578 sprintf(buf, "</TITLE></HEAD>\r\n"); 579 send(client, buf, strlen(buf), 0); 580 sprintf(buf, "<BODY><P>HTTP request method not supported.\r\n"); 581 send(client, buf, strlen(buf), 0); 582 sprintf(buf, "</BODY></HTML>\r\n"); 583 send(client, buf, strlen(buf), 0); 584 } 585 586 /**********************************************************************/ 587 588 int main(void) 589 { 590 /** 591 * 局部變量說明: 592 * 1.server_sock : 服務(wù)器端的socket描述符; 593 * 2.port : 服務(wù)器端的socket端口號(hào),如果是0的,startup()將會(huì)采用 594 * 自動(dòng)生成的方式生成新的端口號(hào)供使用; 595 * 3.client_sock : 客戶端連接進(jìn)來產(chǎn)生的客戶端socket描述符; 596 * 4.client_name : 用于保存客戶端連接進(jìn)來的socket信息; 597 * 5.client_name_len : struct sockaddr_in結(jié)構(gòu)體的大小,在accpet的時(shí)候 598 * 需要用到,這個(gè)參數(shù)必須傳,否則會(huì)出錯(cuò); 599 * 6.newthread : 用于保存新創(chuàng)建的線程的ID. 600 */ 601 int server_sock = -1; 602 u_short port = 0; 603 int client_sock = -1; 604 struct sockaddr_in client_name; 605 int client_name_len = sizeof(client_name); 606 pthread_t newthread; 607 608 /** 609 * startup 函數(shù)完成內(nèi)容: 610 * 1.獲取一個(gè)作為服務(wù)器的socket; 611 * 2.幫定服務(wù)器斷的sockt; 612 * 3.通過判斷參數(shù)port的值,確定是否需要?jiǎng)討B(tài)分配端口號(hào); 613 * 4.服務(wù)器開啟監(jiān)聽. 614 */ 615 server_sock = startup(&port); 616 printf("httpd running on port %d\n", port); 617 618 while (1) 619 { 620 /** 621 * 等待客戶端的連接,使用client_name保存客戶端socket信息, 622 * client_name_len是client_name對(duì)應(yīng)結(jié)構(gòu)體的長度. 623 */ 624 client_sock = accept(server_sock, 625 (struct sockaddr *)&client_name, 626 &client_name_len); 627 if (client_sock == -1) 628 error_die("accept"); 629 /** 630 * 創(chuàng)建一個(gè)新的線程來處理任務(wù),并把客戶端的socket描述符作為參數(shù)傳給accept_request, 631 * accept_request 函數(shù)說明: 632 * 1.獲取請(qǐng)求方式,目前只支持GET、POST請(qǐng)求; 633 * 2.在本程序中所有的POST請(qǐng)求、帶參數(shù)的GET請(qǐng)求都都被定義為訪問cgi程序; 634 * 3.從帶參數(shù)的GET請(qǐng)求中分離出請(qǐng)求參數(shù); 635 * 4.如果沒有指定需要訪問的文件,使用index.html文件作為默認(rèn)訪問文件; 636 * 5.檢查需要訪問的文件是否存在,以及其是否具有對(duì)應(yīng)的權(quán)限; 637 * 6.根據(jù)是否是cgi程序訪問,來執(zhí)行對(duì)應(yīng)的任務(wù). 638 */ 639 if (pthread_create(&newthread , NULL, accept_request, client_sock) != 0) 640 perror("pthread_create"); 641 } 642 643 /** 644 * 不知道為什么,這條語句在while外邊,竟然會(huì)影響到程序的關(guān)閉 :( 645 * 這行代碼注釋掉才能連續(xù)訪問,不注釋,只能訪問一次,所以直接注釋了 646 * 反正程序停止都使用ctrl+c,不影響程序的運(yùn)行. 647 */ 648 //close(server_sock); 649 650 return(0); 651 }

?

轉(zhuǎn)載于:https://www.cnblogs.com/zengjfgit/p/4308459.html

總結(jié)

以上是生活随笔為你收集整理的tinyhttpd-0.1.0_hacking的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 欧美少妇一区二区三区 | 婷婷狠狠操| 久久蜜桃av一区二区天堂 | 色姑娘综合网 | 夜操操| 色播在线观看 | 软萌小仙自慰喷白浆 | 9999视频 | 亚洲人体一区 | 亚洲成人一区 | 日韩欧美二区三区 | 日韩欧美国产激情 | 91婷婷色| 欧美一级久久 | 欧美在线观看www | 亚洲AV无码精品色毛片浪潮 | 欧美另类在线观看 | 国产乱色精品成人免费视频 | 欧美影院一区二区三区 | 欧美福利视频在线观看 | 深夜福利在线播放 | 国产一区二区三区影院 | 人妻互换一区二区激情偷拍 | 日韩免费 | 欧美淫视频 | 国产精品夜夜夜爽阿娇 | 99久久精品一区二区 | 伊人热久久 | av黄色在线免费观看 | 久久一区二区三区四区 | 日韩av在线天堂 | 欧美日韩一区二区三区在线播放 | 欧美成人一区二区三区高清 | 人妻熟女aⅴ一区二区三区汇编 | 精品久久久久久久久久久久 | 锦绣未央在线观看 | 久久久久久天堂 | 色婷视频 | 在线综合网| 韩国三级hd中文字幕 | 久久er99热精品一区二区 | 亚洲偷 | 亚洲福利视频一区二区三区 | 免费在线播放黄色片 | 久久亚洲精选 | 大尺度舌吻呻吟声 | 国产欧美精品一区二区色综合 | 欧美日韩精品在线视频 | 亚洲精品男人天堂 | 国产簧片 | 亚洲砖区免费 | 噼里啪啦国语电影 | 99久久精品免费看国产交换 | 日韩成人av毛片 | 无码少妇一区二区三区 | 亚洲av无码一区东京热久久 | 麻豆视频在线看 | 国产午夜大片 | 日韩精品第一 | 公肉吊粗大爽色翁浪妇视频 | 欧美激情一级 | 欧美中文字幕在线 | 久久综合九色综合欧美狠狠 | 国产亚洲精品久久久久久打不开 | 爱情岛论坛永久入址在线 | 国产精品成人午夜视频 | 午夜视频福利在线 | jizz欧美大片 | 一级片免费在线观看 | 国产一区日韩一区 | 亚洲区一区二区三区 | 成人黄色在线视频 | 色在线播放 | 国产又爽又黄无码无遮挡在线观看 | 视频在线观看一区二区 | 精品欧美乱码久久久久久 | 福利av在线| 亚洲社区在线观看 | 日韩精品综合 | 人人上人人干 | 久久97精品 | 91看片黄 | 香蕉视频18| 五月天久久婷婷 | 欧洲女同同性吃奶 | 成人免费视频网站在线观看 | 久青草视频在线 | 香蕉视频网站 | 男人的天堂色偷偷 | 尹人香蕉 | 国产毛片毛片毛片毛片毛片毛片 | 麻豆影视在线观看 | 青草视频免费观看 | av小说免费在线观看 | 在线免费观看av不卡 | 秋霞在线一区二区 | 69欧美视频| gai免费观看网站外网 | 性一交一乱一乱一视频 |