webbench 代码阅读
簡(jiǎn)介:
Webbech能測(cè)試處在相同硬件上,不同服務(wù)的性能以及不同硬件上同一個(gè)服務(wù)的運(yùn)行狀況.webBech的標(biāo)準(zhǔn)測(cè)試可以向我們展示服務(wù)器的兩項(xiàng) 內(nèi)容:每秒鐘相應(yīng)請(qǐng)求數(shù)和每秒鐘傳輸數(shù)據(jù)量.webbench不但能具有便準(zhǔn)靜態(tài)頁(yè)面的測(cè)試能力,還能對(duì)動(dòng)態(tài)頁(yè)面(ASP,PHP,JAVA,CGI)進(jìn) 行測(cè)試的能力.還有就是他支持對(duì)含有SSL的安全網(wǎng)站例如電子商務(wù)網(wǎng)站進(jìn)行靜態(tài)或動(dòng)態(tài)的性能測(cè)試.
×××××××××××××××××××××××××吐槽,可忽略××××××××××××××××××××××
好吧 , 我承認(rèn)好高端,但整個(gè)代碼也就幾百行,還是算上注釋呀,看完之后,完全沒(méi)有什么動(dòng)態(tài)網(wǎng)頁(yè)測(cè)試,SSL 安全網(wǎng)站測(cè)試什么選項(xiàng)呀!!!!
,只有選擇http協(xié)議的請(qǐng)求頭選項(xiàng)呀,什么GET,HEAD,之類(lèi)的
×××××××××××××××××××××××××××××××××××××××××××××××××××××
?
了解代碼,你先得了解它的業(yè)務(wù)流程
難點(diǎn)一:獲取web服務(wù)器信息
解決這個(gè)問(wèn)題,首先你的了解你要測(cè)試什么? 你要測(cè)試的是一個(gè)web服務(wù)器應(yīng)對(duì)大量請(qǐng)求的能力,就是所說(shuō)的壓力測(cè)試。你要做的是同時(shí)構(gòu)造大量的請(qǐng)求,達(dá)到測(cè)試目的。
請(qǐng)求是由 URL 地址連接 指示的,你要明白URL 地址連接由什么組成,你需要從其中獲取那些必要的信息構(gòu)成請(qǐng)求。url的一般模式為
http://myname:mypass@www.vimer.cn:80/mydir/myfile.html?myvar=myvalue#myfrag
| URI部分 | 意義 |
| http | 協(xié)議名稱 |
| myname | 用戶名(可選) |
| mypass | 密碼(可選) |
| www.vimer.cn | 主機(jī)網(wǎng)絡(luò)地址 |
| 80 | 端口號(hào)(可選) |
| /mydir/myfile.html | 資源路徑 |
| myvar=myvalue | 查詢字符串(可選) |
| myfrag | 錨點(diǎn)(可選) ? |
要從url 提取 host 和 request ,host是主機(jī)網(wǎng)絡(luò)地址,reques 是利用http請(qǐng)求頭和資源路徑構(gòu)成的一個(gè)http協(xié)議請(qǐng)求,web服務(wù)器會(huì)處理這個(gè)請(qǐng)求并且返回資源,一個(gè)例子:??
輸入: http://www.vimer.cn/2010/02/%e7%ae%80%e6%98%8ehttp%e5%8d%8f%e8%ae%ae.html host www.vimer.cn request GET /2010/02/%e7%ae%80%e6%98%8ehttp%e5%8d%8f%e8%ae%ae.html HTTP/1.0如果你縱覽了代碼,可以說(shuō)60%的功能都用來(lái)進(jìn)行字符串操作,來(lái)獲得?host 和 request ?不無(wú)論是mian函數(shù)還build_request 都是來(lái)實(shí)現(xiàn)這個(gè)功能的。具體的細(xì)節(jié)實(shí)現(xiàn)可以參考代碼注釋,注意一下,使用了大量的字符串函數(shù),隨時(shí)要準(zhǔn)備man一下。
難點(diǎn)二:如何測(cè)評(píng),依據(jù)是什么
? ?測(cè)試就的有一個(gè)標(biāo)準(zhǔn),webbench的標(biāo)準(zhǔn)是成功使用stock建立的http鏈接,benchwork函數(shù)做的就是這樣一項(xiàng)工作。webbench使用的是多進(jìn)程操作,
它選用了通道作為parent和childern的聯(lián)系方式,來(lái)告知parent,child成功或失敗建立了幾個(gè)連接,傳送的總的字節(jié)數(shù)是多少。在博文的最后有一個(gè)benchwork函數(shù)的流程圖,有興趣的可以看一下
?
代碼
webbench.c
?
1 /* 2 * (C) Radim Kolar 1997-2004 3 * This is free software, see GNU Public License version 2 for 4 * details. 5 * 6 * Simple forking WWW Server benchmark: 7 * 8 * Usage: 9 * webbench --help 10 * 11 * Return codes: 12 * 0 - sucess 13 * 1 - benchmark failed (server is not on-line) 14 * 2 - bad param 15 * 3 - internal error, fork failed 16 * 17 */ 18 #include "socket.c" 19 #include <unistd.h> 20 #include <sys/param.h> //描述系統(tǒng)參數(shù) 21 #include <rpc/types.h> 22 #include <getopt.h>//參數(shù)分析 23 #include <strings.h> 24 #include <time.h> 25 #include <signal.h>//信號(hào)處理 26 27 /* values */ 28 volatile int timerexpired=0; 29 /* volatile 30 * 提示編譯器所定義的變量隨時(shí)可能改變,因此編譯后的程序每次需要存儲(chǔ)或是i 31 * 讀取該變量的時(shí)候,都會(huì)直接從變量地址讀取數(shù)據(jù)。 32 * 之所以要這樣做,是因?yàn)榫幾g器會(huì)對(duì)代碼的讀取和存儲(chǔ)進(jìn)行優(yōu)化,可能暫時(shí)使用 33 * 寄存器的值。 34 * */ 35 int speed=0; 36 int failed=0; 37 int bytes=0; 38 /* globals */ 39 int http10=1; /* 0 - http/0.9, 1 - http/1.0, 2 - http/1.1 */ 40 /* Allow: GET, HEAD, OPTIONS, TRACE */ 41 #define METHOD_GET 0 42 #define METHOD_HEAD 1 43 #define METHOD_OPTIONS 2 44 #define METHOD_TRACE 3 45 #define PROGRAM_VERSION "1.5" 46 int method=METHOD_GET; 47 int clients=1;/* 測(cè)試進(jìn)程數(shù),默認(rèn)1:w*/ 48 int force=0;/* 等待服務(wù)器返回標(biāo)志 ,默認(rèn)為等待返回 0 */ 49 int force_reload=0; 50 int proxyport=80;/* 服務(wù)器端口號(hào),http協(xié)議默認(rèn)為80端口*/ 51 char *proxyhost=NULL;//代理服務(wù)器 52 int benchtime=30;/* 運(yùn)行時(shí)間,默認(rèn)為30 */ 53 /* internal */ 54 int mypipe[2]; /* 通道 */ 55 char host[MAXHOSTNAMELEN];/* 域名 */ 56 #define REQUEST_SIZE 2048 57 char request[REQUEST_SIZE];/* http 請(qǐng)求頭 */ 58 59 static const struct option long_options[]= 60 { 61 {"force",no_argument,&force,1}, 62 {"reload",no_argument,&force_reload,1}, 63 {"time",required_argument,NULL,'t'}, 64 {"help",no_argument,NULL,'?'}, 65 {"http09",no_argument,NULL,'9'}, 66 {"http10",no_argument,NULL,'1'}, 67 {"http11",no_argument,NULL,'2'}, 68 {"get",no_argument,&method,METHOD_GET}, 69 {"head",no_argument,&method,METHOD_HEAD}, 70 {"options",no_argument,&method,METHOD_OPTIONS}, 71 {"trace",no_argument,&method,METHOD_TRACE}, 72 {"version",no_argument,NULL,'V'}, 73 {"proxy",required_argument,NULL,'p'}, 74 {"clients",required_argument,NULL,'c'}, 75 {NULL,0,NULL,0} 76 }; 77 /* 靜態(tài)函數(shù) 78 * 特性: 79 * 1.周期:整個(gè)程序,范圍:本文件 80 * 2.使用static作為前綴,僅可以本文件函數(shù)調(diào)用, 81 * 不能被同一程序的其他文件調(diào)用 82 * 3.可以在不同文件里使用相同的函數(shù)名,不用擔(dān)心沖突 83 * */ 84 /* prototypes */ 85 static void benchcore(const char* host,const int port, const char *request); 86 /* 測(cè)試 host 的連接 功能函數(shù) */ 87 static int bench(void); 88 /* 測(cè)試 host 的前期準(zhǔn)備 和 多進(jìn)程操作與同行 */ 89 static void build_request(const char *url); 90 /* 解析 request */ 91 92 static void alarm_handler(int signal) 93 /* 和sig 和signaction 構(gòu)成一個(gè)時(shí)鐘 */ 94 { 95 timerexpired=1; 96 } 97 98 static void usage(void) 99 /* 幫助 */ 100 { 101 fprintf(stderr, 102 "webbench [option]... URL\n" 103 " -f|--force Don't wait for reply from server.\n" 104 " -r|--reload Send reload request - Pragma: no-cache.\n" 105 " -t|--time <sec> Run benchmark for <sec> seconds. Default 30.\n" 106 " -p|--proxy <server:port> Use proxy server for request.\n" 107 " -c|--clients <n> Run <n> HTTP clients at once. Default one.\n" 108 " -9|--http09 Use HTTP/0.9 style requests.\n" 109 " -1|--http10 Use HTTP/1.0 protocol.\n" 110 " -2|--http11 Use HTTP/1.1 protocol.\n" 111 " --get Use GET request method.\n" 112 " --head Use HEAD request method.\n" 113 " --options Use OPTIONS request method.\n" 114 " --trace Use TRACE request method.\n" 115 " -?|-h|--help This information.\n" 116 " -V|--version Display program version.\n" 117 ); 118 }; 119 int main(int argc, char *argv[]) 120 { 121 int opt=0; 122 int options_index=0; 123 char *tmp=NULL; 124 125 if(argc==1) 126 { 127 usage(); 128 return 2; 129 } 130 131 while((opt=getopt_long(argc,argv,"912Vfrt:p:c:?h",long_options,&options_index))!=EOF ) 132 /* 使用getopt 函數(shù) 獲取分析命令,對(duì)一些參數(shù)進(jìn)行設(shè)置 */ 133 { 134 switch(opt) 135 { 136 case 0 : break; 137 case 'f': force=1;break;//Don't wait for reply from server 138 case 'r': force_reload=1;break;//Send reload request - Pragma: no-cache 139 case '9': http10=0;break; 140 case '1': http10=1;break; 141 case '2': http10=2;break; 142 case 'V': printf(PROGRAM_VERSION"\n");exit(0); 143 case 't': benchtime=atoi(optarg);break;//optarg[ getopt的全局變量 ] : 指向當(dāng)前選項(xiàng)參數(shù)的指針 144 case 'p': 145 /* proxy server parsing server:port */ 146 tmp=strrchr(optarg,':'); 147 /* char * strrchr(const char * s,int c ) 148 * 返回 字符c 在字符串s末次出現(xiàn)的位置【返回值指向的是'c' 149 * */ 150 /* 返回的是端口號(hào) 151 * */ 152 proxyhost=optarg; 153 if(tmp==NULL) 154 { 155 break; 156 } 157 if(tmp==optarg) 158 { 159 fprintf(stderr,"Error in option --proxy %s: Missing hostname.\n",optarg); 160 return 2; 161 }//只有 :port 162 if(tmp==optarg+strlen(optarg)-1) 163 { 164 fprintf(stderr,"Error in option --proxy %s Port number is missing.\n",optarg); 165 return 2; 166 }//只有 server: 167 *tmp='\0'; 168 proxyport=atoi(tmp+1);break;//獲取端口號(hào) 169 case ':': 170 case 'h': 171 case '?': usage();return 2;break; 172 case 'c': clients=atoi(optarg);break; 173 } 174 } 175 176 if(optind==argc) { 177 /* optind getopt_long 函數(shù)的全局變量 ,表示下一個(gè)要解析的參數(shù)的位置 178 * 初始值為 1 179 180 可以這么理解: 181 如果一個(gè)程序有一個(gè)參數(shù)是必須需要的,則optind < argv,例如 webbench需要一個(gè)測(cè)試 182 目標(biāo)URL,那么 webbench 會(huì)占用 0 的下標(biāo),而optind 已經(jīng)默認(rèn)初始化為1,可以預(yù)見(jiàn) 183 參數(shù)和參數(shù)的選項(xiàng)都會(huì)被getopt()操作后,optind 會(huì)指向下一個(gè)下標(biāo)[無(wú)論是否存在], 184 不存在的話, optind就會(huì)和 argc 相等,相當(dāng)于只輸入了一個(gè)webbench , 185 optind == argc == 1 , 186 * */ 187 fprintf(stderr,"webbench: Missing URL!\n"); 188 usage(); 189 return 2; 190 } 191 192 if(clients==0) clients=1; 193 if(benchtime==0) benchtime=60; 194 /* Copyright */ 195 fprintf(stderr,"Webbench - Simple Web Benchmark "PROGRAM_VERSION"\n" 196 "Copyright (c) Radim Kolar 1997-2004, GPL Open Source Software.\n" 197 ); 198 build_request(argv[optind]); 199 /* print bench info */ 200 printf("\nBenchmarking: "); 201 switch(method) 202 { 203 case METHOD_GET: 204 default: 205 printf("GET");break; 206 case METHOD_OPTIONS: 207 printf("OPTIONS");break; 208 case METHOD_HEAD: 209 printf("HEAD");break; 210 case METHOD_TRACE: 211 printf("TRACE");break; 212 } 213 // printf(" %s",argv[optind]); 214 switch(http10) 215 { 216 case 0: printf(" (using HTTP/0.9)");break; 217 case 2: printf(" (using HTTP/1.1)");break; 218 } 219 printf("\n"); 220 if(clients==1) printf("1 client"); 221 else 222 printf("%d clients",clients); 223 224 printf(", running %d sec", benchtime); 225 if(force) printf(", early socket close"); 226 if(proxyhost!=NULL) printf(", via proxy server %s:%d",proxyhost,proxyport); 227 if(force_reload) printf(", forcing reload"); 228 printf(".\n"); 229 return bench(); 230 } 231 232 void build_request(const char *url) 233 { 234 char tmp[10]; 235 int i; 236 237 bzero(host,MAXHOSTNAMELEN); 238 bzero(request,REQUEST_SIZE); 239 /* 初始化空間為0 */ 240 241 if(force_reload && proxyhost!=NULL && http10<1) http10=1; 242 if(method==METHOD_HEAD && http10<1) http10=1; 243 if(method==METHOD_OPTIONS && http10<2) http10=2; 244 if(method==METHOD_TRACE && http10<2) http10=2; 245 /* 不知所以 ,缺少fftp的基本的基本知識(shí) */ 246 247 switch(method) 248 { 249 default: 250 case METHOD_GET: strcpy(request,"GET");break; 251 case METHOD_HEAD: strcpy(request,"HEAD");break; 252 case METHOD_OPTIONS: strcpy(request,"OPTIONS");break; 253 case METHOD_TRACE: strcpy(request,"TRACE");break; 254 } 255 256 strcat(request," "); 257 258 if(NULL==strstr(url,"://")) 259 { 260 fprintf(stderr, "\n%s: is not a valid URL.\n",url); 261 exit(2); 262 } 263 if(strlen(url)>1500) 264 { 265 fprintf(stderr,"URL is too long.\n"); 266 exit(2); 267 } 268 if(proxyhost==NULL) 269 if (0!=strncasecmp("http://",url,7)) 270 /* int strncasecmp(char *s1,char *s2,int i) 271 * 只比較s1的前 i 位和 s2的關(guān)系 272 * */ 273 { fprintf(stderr,"\nOnly HTTP protocol is directly supported, set --proxy for others.\n"); 274 exit(2); 275 } 276 /* protocol/host delimiter */ 277 i=strstr(url,"://")-url+3; 278 //printf("strstr(url,""): %p, url :%p, i = %d \n",strstr(url,"://"),url,i); 279 /* 根據(jù) 數(shù)組在內(nèi)存中存放的形式, 可以利用 strstr(..) 求的地址A,同時(shí)利用 url的 280 * 地址 B, A-B = 4[ 從低位開(kāi)始放,就像壓棧一樣 ], 281 * 最后的 i 表示 一個(gè)http網(wǎng)址中, :// 之后的第一字符的下標(biāo) 282 * 例如: http;//www.yankanshu.com .i 表示 w的下標(biāo)位置 283 * */ 284 285 if(strchr(url+i,'/')==NULL) { 286 fprintf(stderr,"\nInvalid URL syntax - hostname don't ends with '/'.\n"); 287 exit(2); 288 } 289 if(proxyhost==NULL) 290 { 291 /* get port from hostname */ 292 if(index(url+i,':')!=NULL && 293 index(url+i,':')<index(url+i,'/')) 294 { 295 // printf("test 1\n "); 296 strncpy(host,url+i,strchr(url+i,':')-url-i); 297 bzero(tmp,10); 298 strncpy(tmp,index(url+i,':')+1,strchr(url+i,'/')-index(url+i,':')-1); 299 /* printf("tmp=%s\n",tmp); */ 300 proxyport=atoi(tmp); 301 if(proxyport==0) proxyport=80; 302 } else 303 { 304 // printf("test 2\n "); 305 strncpy(host,url+i,strcspn(url+i,"/")); 306 } 307 // printf("Host=%s\n",host); 308 /* 最后的host 是不帶 http: 和 最后的 \ 309 * 例如: http://baike.baidu.com/ 310 * host = baike.baidu.com 311 * */ 312 strcat(request+strlen(request),url+i+strcspn(url+i,"/")); 313 /*沒(méi)有理解目的 : 314 * 根據(jù)測(cè)試: 315 * GET 變成了 GET /.....*/ 316 } else 317 { 318 // printf("ProxyHost=%s\nProxyPort=%d\n",proxyhost,proxyport); 319 strcat(request,url); 320 } 321 if(http10==1) 322 strcat(request," HTTP/1.0"); 323 else if (http10==2) 324 strcat(request," HTTP/1.1"); 325 strcat(request,"\r\n"); 326 if(http10>0) 327 strcat(request,"User-Agent: WebBench "PROGRAM_VERSION"\r\n"); 328 /* 字符串組合技巧 329 * */ 330 if(proxyhost==NULL && http10>0) 331 { 332 strcat(request,"Host: "); 333 strcat(request,host); 334 strcat(request,"\r\n"); 335 } 336 if(force_reload && proxyhost!=NULL) 337 { 338 strcat(request,"Pragma: no-cache\r\n"); 339 } 340 if(http10>1) 341 strcat(request,"Connection: close\r\n"); 342 /* add empty line at end */ 343 if(http10>0) strcat(request,"\r\n"); 344 // printf("Req=%s\n",request); 345 } 346 347 /* vraci system rc error kod */ 348 static int bench(void) 349 { 350 int i,j,k; 351 pid_t pid=0; 352 FILE *f; 353 354 /* check avaibility of target server */ 355 // printf("commmd: proxyhost= host %s proxhost %s\n",host,proxyhost); 356 i=Socket(proxyhost==NULL?host:proxyhost,proxyport); 357 //printf("commd: test3\n"); 358 359 /* 建立測(cè)試網(wǎng)址的套接字 360 * 可以后的host的直接使用host 361 * 不可以的利用gethostbyname函數(shù)通過(guò)域名解析獲得host 362 * */ 363 if(i<0) { 364 fprintf(stderr,"\nConnect to server failed. Aborting benchmark.\n"); 365 return 1; 366 } 367 close(i); 368 /* create pipe */ 369 if(pipe(mypipe)) 370 /* 進(jìn)程間的通信方式 371 * 通道 372 * */ 373 { 374 perror("pipe failed."); 375 return 3; 376 } 377 378 /* not needed, since we have alarm() in childrens */ 379 /* wait 4 next system clock tick */ 380 /* 381 cas=time(NULL); 382 while(time(NULL)==cas) 383 sched_yield(); 384 */ 385 386 /* fork childs */ 387 for(i=0;i<clients;i++) 388 { 389 pid=fork(); 390 if(pid <= (pid_t) 0)// 為了防止什么 ???? 391 { 392 /* child process or error*/ 393 sleep(1); /* make childs faster */ 394 break; 395 } 396 } 397 398 if( pid< (pid_t) 0) 399 { 400 fprintf(stderr,"problems forking worker no. %d\n",i); 401 perror("fork failed."); 402 return 3; 403 } 404 405 if(pid== (pid_t) 0) 406 { 407 printf("commnd:request:%s\n",request); 408 /* I am a child */ 409 if(proxyhost==NULL) 410 benchcore(host,proxyport,request); 411 else 412 benchcore(proxyhost,proxyport,request); 413 414 /* write results to pipe */ 415 f=fdopen(mypipe[1],"w"); 416 if(f==NULL) 417 { 418 perror("open pipe for writing failed."); 419 return 3; 420 } 421 /* fprintf(stderr,"Child - %d %d\n",speed,failed); */ 422 fprintf(f,"%d %d %d\n",speed,failed,bytes); 423 fclose(f); 424 return 0; 425 } else 426 { 427 f=fdopen(mypipe[0],"r"); 428 if(f==NULL) 429 { 430 perror("open pipe for reading failed."); 431 return 3; 432 } 433 /* 作為一個(gè)讀的文件流,為什么要設(shè)置成 nobuf ???? 434 * */ 435 setvbuf(f,NULL,_IONBF,0); 436 speed=0; 437 failed=0; 438 bytes=0; 439 440 while(1) 441 { 442 pid=fscanf(f,"%d %d %d",&i,&j,&k); 443 if(pid<2) 444 { 445 fprintf(stderr,"Some of our childrens died.\n"); 446 break; 447 } 448 speed+=i; 449 failed+=j; 450 bytes+=k; 451 /* fprintf(stderr,"*Knock* %d %d read=%d\n",speed,failed,pid); */ 452 if(--clients==0) break; 453 } 454 fclose(f); 455 456 printf("\nSpeed=%d pages/min, %d bytes/sec.\nRequests: %d susceed, %d failed.\n", 457 (int)((speed+failed)/(benchtime/60.0f)), 458 (int)(bytes/(float)benchtime), 459 speed, 460 failed); 461 } 462 return i; 463 } 464 465 void benchcore(const char *host,const int port,const char *req) 466 { 467 int rlen; 468 char buf[1500]; 469 int s,i; 470 struct sigaction sa; 471 472 /* setup alarm signal handler */ 473 sa.sa_handler=alarm_handler; 474 sa.sa_flags=0; 475 if(sigaction(SIGALRM,&sa,NULL)) 476 /* SIGALRM 是 定時(shí)器終止時(shí)發(fā)送給進(jìn)程的信號(hào) 477 * SIG 是信號(hào)名的通用前綴,ALRM是alarm的縮寫(xiě) 478 * 通常作為長(zhǎng)時(shí)間操作的超時(shí)信號(hào) 479 * 或者提供一種隔一定時(shí)間處理某些操作的方式 480 * 一般是在調(diào)用 alarm(t ) t秒后出現(xiàn) 481 * */ 482 exit(3); 483 alarm(benchtime); 484 /* sigcation 和 alarm 設(shè)置了一個(gè)鬧鐘,用來(lái)定時(shí)退出 */ 485 486 rlen=strlen(req); 487 nexttry:while(1) 488 { 489 if(timerexpired) 490 { 491 if(failed>0) 492 { 493 /* fprintf(stderr,"Correcting failed by signal\n"); */ 494 failed--; 495 } 496 return; 497 } 498 s=Socket(host,port); 499 if(s<0) { failed++;continue;} 500 /* 申請(qǐng)建立連接失敗, fail++ 501 * */ 502 if(rlen!=write(s,req,rlen)) {failed++;close(s);continue;} 503 /* 無(wú)法寫(xiě)入套接字,算是失敗吧 ???? 504 * fail++ 505 * */ 506 if(http10==0) 507 /*http 0.9 進(jìn)行關(guān)閉操作 ????*/ 508 if(shutdown(s,1)) 509 /* 1 終止 傳送操作 */ 510 { failed++;close(s);continue;} 511 if(force==0) 512 /* 阻塞等待回應(yīng) 513 */ 514 { 515 /* read all available data from socket */ 516 while(1) 517 { 518 if(timerexpired) break; 519 i=read(s,buf,1500); 520 //fprintf(stderr,"%d\n",i); 521 // fprintf(stderr,"%s",buf); 522 if(i<0) 523 { 524 failed++; 525 close(s); 526 goto nexttry; 527 } 528 else 529 if(i==0) break; 530 else 531 bytes+=i; 532 } 533 } 534 if(close(s)) {failed++;continue;} 535 speed++; 536 } 537 }?
socket.c
?
1 /* $Id: socket.c 1.1 1995/01/01 07:11:14 cthuang Exp $ 2 * 3 * This module has been modified by Radim Kolar for OS/2 emx 4 */ 5 6 /*********************************************************************** 7 module: socket.c 8 program: popclient 9 SCCS ID: @(#)socket.c 1.5 4/1/94 10 programmer: Virginia Tech Computing Center 11 compiler: DEC RISC C compiler (Ultrix 4.1) 12 environment: DEC Ultrix 4.3 13 description: UNIX sockets code. 14 ***********************************************************************/ 15 16 #include <sys/types.h> 17 #include <sys/socket.h> 18 #include <fcntl.h> 19 #include <netinet/in.h> 20 #include <arpa/inet.h> 21 #include <netdb.h> 22 #include <sys/time.h> 23 #include <string.h> 24 #include <unistd.h> 25 #include <stdio.h> 26 #include <stdlib.h> 27 #include <stdarg.h> 28 29 int Socket(const char *host, int clientPort) 30 { 31 int sock; 32 unsigned long inaddr; 33 struct sockaddr_in ad; 34 struct hostent *hp; 35 36 // printf("%s\n",host); 37 memset(&ad, 0, sizeof(ad)); 38 ad.sin_family = AF_INET; 39 40 inaddr = inet_addr(host); 41 if (inaddr != INADDR_NONE) 42 /* 無(wú)符號(hào)長(zhǎng)整型和負(fù)數(shù)比較 43 * 上面這句話有問(wèn)題, iner_addr 返回一個(gè)FFFFFFFF,即-1為錯(cuò)誤,在ip地址翻譯上 44 * 255.255.255.255,這個(gè)也就是 為什么不建議使用 inet_addr的原因*/ 45 memcpy(&ad.sin_addr, &inaddr, sizeof(inaddr)); 46 else 47 { 48 // printf("test 4\n"); 49 hp = gethostbyname(host); 50 // printf("test 5\n"); 51 if (hp == NULL) 52 return -1; 53 memcpy(&ad.sin_addr, hp->h_addr, hp->h_length); 54 } 55 ad.sin_port = htons(clientPort); 56 57 sock = socket(AF_INET, SOCK_STREAM, 0); 58 if (sock < 0) 59 return sock; 60 if (connect(sock, (struct sockaddr *)&ad, sizeof(ad)) < 0) 61 return -1; 62 return sock; 63 }?
?
**************************************************************************************************
最后放一些寫(xiě)個(gè)自己的東西
1. 我學(xué)到的字符串更加靈活的應(yīng)用,尤其是幾個(gè)以前沒(méi)有見(jiàn)過(guò)的string.h庫(kù)里的函數(shù)
2. 對(duì)http協(xié)議有了個(gè)初步的了解 : http簡(jiǎn)明解析
3. getopt函數(shù)的使用的了解
?
?
?
?
??
? ?
?
轉(zhuǎn)載于:https://www.cnblogs.com/dilidingzhi/p/4298096.html
總結(jié)
以上是生活随笔為你收集整理的webbench 代码阅读的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 【hibernate框架】一对多(多对一
- 下一篇: 【转】(六)unity4.6Ugui中文