zoukankan      html  css  js  c++  java
  • webbench 代码阅读

     

    简介:

    Webbech能测试处在相同硬件上,不同服务的性能以及不同硬件上同一个服务的运行状况.webBech的标准测试可以向我们展示服务器的两项 内容:每秒钟相应请求数和每秒钟传输数据量.webbench不但能具有便准静态页面的测试能力,还能对动态页面(ASP,PHP,JAVA,CGI)进 行测试的能力.还有就是他支持对含有SSL的安全网站例如电子商务网站进行静态或动态的性能测试.

    ×××××××××××××××××××××××××吐槽,可忽略××××××××××××××××××××××

     好吧 , 我承认好高端,但整个代码也就几百行,还是算上注释呀,看完之后,完全没有什么动态网页测试,SSL 安全网站测试什么选项呀!!!!

    ,只有选择http协议的请求头选项呀,什么GET,HEAD,之类的

    ×××××××××××××××××××××××××××××××××××××××××××××××××××××

    了解代码,你先得了解它的业务流程

     难点一:获取web服务器信息

         解决这个问题,首先你的了解你要测试什么? 你要测试的是一个web服务器应对大量请求的能力,就是所说的压力测试。你要做的是同时构造大量的请求,达到测试目的。

         请求是由 URL 地址连接 指示的,你要明白URL 地址连接由什么组成,你需要从其中获取那些必要的信息构成请求。url的一般模式为

        http://myname:mypass@www.vimer.cn:80/mydir/myfile.html?myvar=myvalue#myfrag

          

    URI部分

    意义

    http

    协议名称

    myname

    用户名(可选)

    mypass

    密码(可选)

    www.vimer.cn

    主机网络地址

    80

    端口号(可选)

    /mydir/myfile.html

    资源路径

    myvar=myvalue

    查询字符串(可选)

    myfrag

    锚点(可选)

      要从url 提取 host 和 request ,host是主机网络地址,reques 是利用http请求头和资源路径构成的一个http协议请求,web服务器会处理这个请求并且返回资源,一个例子:  

        输入: 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

    如果你纵览了代码,可以说60%的功能都用来进行字符串操作,来获得 hostrequest  不无论是mian函数还build_request 都是来实现这个功能的。具体的细节实现可以参考代码注释,注意一下,使用了大量的字符串函数,随时要准备man一下。

    难点二:如何测评,依据是什么

       测试就的有一个标准,webbench的标准是成功使用stock建立的http链接,benchwork函数做的就是这样一项工作。webbench使用的是多进程操作,

    它选用了通道作为parent和childern的联系方式,来告知parent,child成功或失败建立了几个连接,传送的总的字节数是多少。在博文的最后有一个benchwork函数的流程图,有兴趣的可以看一下

    代码

    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> //描述系统参数
     21 #include <rpc/types.h>
     22 #include <getopt.h>//参数分析
     23 #include <strings.h>
     24 #include <time.h>
     25 #include <signal.h>//信号处理
     26 
     27 /* values */
     28 volatile int timerexpired=0;
     29 /*  volatile  
     30  *  提示编译器所定义的变量随时可能改变,因此编译后的程序每次需要存储或是i
     31  *  读取该变量的时候,都会直接从变量地址读取数据。
     32  *  之所以要这样做,是因为编译器会对代码的读取和存储进行优化,可能暂时使用
     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;/* 测试进程数,默认1:w*/
     48 int force=0;/* 等待服务器返回标志 ,默认为等待返回 0 */
     49 int force_reload=0;
     50 int proxyport=80;/* 服务器端口号,http协议默认为80端口*/
     51 char *proxyhost=NULL;//代理服务器
     52 int benchtime=30;/* 运行时间,默认为30 */
     53 /* internal */
     54 int mypipe[2];                    /* 通道 */
     55 char host[MAXHOSTNAMELEN];/* 域名 */
     56 #define REQUEST_SIZE 2048
     57 char request[REQUEST_SIZE];/* http 请求头 */
     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 /*  静态函数
     78  *  特性:
     79  *  1.周期:整个程序,范围:本文件
     80  *  2.使用static作为前缀,仅可以本文件函数调用,
     81  *  不能被同一程序的其他文件调用
     82  *  3.可以在不同文件里使用相同的函数名,不用担心冲突
     83  * */
     84 /* prototypes */
     85 static void benchcore(const char* host,const int port, const char *request);
     86 /* 测试 host 的连接 功能函数 */
     87 static int bench(void);
     88 /* 测试 host 的前期准备 和 多进程操作与同行 */
     89 static void build_request(const char *url);
     90 /* 解析 request */
     91 
     92 static void alarm_handler(int signal)
     93 /* 和sig 和signaction 构成一个时钟 */
     94 {
     95    timerexpired=1;
     96 }    
     97 
     98 static void usage(void)
     99 /* 帮助 */
    100 {
    101    fprintf(stderr,
    102     "webbench [option]... URL
    "
    103     "  -f|--force               Don't wait for reply from server.
    "
    104     "  -r|--reload              Send reload request - Pragma: no-cache.
    "
    105     "  -t|--time <sec>          Run benchmark for <sec> seconds. Default 30.
    "
    106     "  -p|--proxy <server:port> Use proxy server for request.
    "
    107     "  -c|--clients <n>         Run <n> HTTP clients at once. Default one.
    "
    108     "  -9|--http09              Use HTTP/0.9 style requests.
    "
    109     "  -1|--http10              Use HTTP/1.0 protocol.
    "
    110     "  -2|--http11              Use HTTP/1.1 protocol.
    "
    111     "  --get                    Use GET request method.
    "
    112     "  --head                   Use HEAD request method.
    "
    113     "  --options                Use OPTIONS request method.
    "
    114     "  --trace                  Use TRACE request method.
    "
    115     "  -?|-h|--help             This information.
    "
    116     "  -V|--version             Display program version.
    "
    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 函数 获取分析命令,对一些参数进行设置 */
    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"
    ");exit(0);
    143    case 't': benchtime=atoi(optarg);break;//optarg[ getopt的全局变量 ] : 指向当前选项参数的指针         
    144    case 'p': 
    145           /* proxy server parsing server:port */
    146          tmp=strrchr(optarg,':');
    147              /*  char * strrchr(const char * s,int c )
    148               *  返回 字符c 在字符串s末次出现的位置【返回值指向的是'c'
    149               * */
    150              /* 返回的是端口号
    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.
    ",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.
    ",optarg);
    165              return 2;
    166          }//只有 server: 
    167          *tmp='';
    168          proxyport=atoi(tmp+1);break;//获取端口号
    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 函数的全局变量 ,表示下一个要解析的参数的位置 
    178           * 初始值为 1 
    179           
    180             可以这么理解:
    181             如果一个程序有一个参数是必须需要的,则optind < argv,例如 webbench需要一个测试
    182             目标URL,那么 webbench 会占用  0 的下标,而optind 已经默认初始化为1,可以预见
    183             参数和参数的选项都会被getopt()操作后,optind 会指向下一个下标[无论是否存在],
    184             不存在的话, optind就会和 argc 相等,相当于只输入了一个webbench , 
    185             optind == argc == 1 ,
    186           * */
    187                       fprintf(stderr,"webbench: Missing URL!
    ");
    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"
    "
    196      "Copyright (c) Radim Kolar 1997-2004, GPL Open Source Software.
    "
    197      );
    198  build_request(argv[optind]);
    199  /* print bench info */
    200  printf("
    Benchmarking: ");
    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("
    ");
    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(".
    ");
    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的基本的基本知识 */
    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, "
    %s: is not a valid URL.
    ",url);
    261       exit(2);
    262   }
    263   if(strlen(url)>1500)
    264   {
    265          fprintf(stderr,"URL is too long.
    ");
    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的关系  
    272                     * */
    273        { fprintf(stderr,"
    Only HTTP protocol is directly supported, set --proxy for others.
    ");
    274              exit(2);
    275            }
    276   /* protocol/host delimiter */
    277   i=strstr(url,"://")-url+3;
    278   //printf("strstr(url,""): %p, url :%p, i = %d  
    ",strstr(url,"://"),url,i);
    279   /*  根据 数组在内存中存放的形式, 可以利用 strstr(..) 求的地址A,同时利用 url的
    280    *  地址 B, A-B = 4[ 从低位开始放,就像压栈一样 ], 
    281    *  最后的 i 表示 一个http网址中, :// 之后的第一字符的下标
    282    *  例如: http;//www.yankanshu.com .i 表示 w的下标位置
    283    * */
    284 
    285   if(strchr(url+i,'/')==NULL) {
    286                                 fprintf(stderr,"
    Invalid URL syntax - hostname don't ends with '/'.
    ");
    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
     ");
    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
    ",tmp); */
    300        proxyport=atoi(tmp);
    301        if(proxyport==0) proxyport=80;
    302    } else
    303    {
    304   //   printf("test 2
     ");
    305      strncpy(host,url+i,strcspn(url+i,"/"));
    306    }
    307   // printf("Host=%s
    ",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    /*没有理解目的 :
    314     * 根据测试:
    315     *  GET 变成了 GET /.....*/
    316   } else
    317   {
    318    // printf("ProxyHost=%s
    ProxyPort=%d
    ",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,"
    ");
    326   if(http10>0)
    327       strcat(request,"User-Agent: WebBench "PROGRAM_VERSION"
    ");
    328           /*  字符串组合技巧
    329            * */
    330   if(proxyhost==NULL && http10>0)
    331   {
    332       strcat(request,"Host: ");
    333       strcat(request,host);
    334       strcat(request,"
    ");
    335   }
    336   if(force_reload && proxyhost!=NULL)
    337   {
    338       strcat(request,"Pragma: no-cache
    ");
    339   }
    340   if(http10>1)
    341       strcat(request,"Connection: close
    ");
    342   /* add empty line at end */
    343   if(http10>0) strcat(request,"
    "); 
    344   // printf("Req=%s
    ",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
    ",host,proxyhost);
    356   i=Socket(proxyhost==NULL?host:proxyhost,proxyport);
    357   //printf("commd: test3
    ");
    358 
    359   /*  建立测试网址的套接字 
    360    *  可以后的host的直接使用host
    361    *  不可以的利用gethostbyname函数通过域名解析获得host
    362    * */
    363   if(i<0) { 
    364        fprintf(stderr,"
    Connect to server failed. Aborting benchmark.
    ");
    365            return 1;
    366          }
    367   close(i);
    368   /* create pipe */
    369   if(pipe(mypipe))
    370           /* 进程间的通信方式 
    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
    ",i);
    401       perror("fork failed.");
    402       return 3;
    403   }
    404 
    405   if(pid== (pid_t) 0)
    406   {
    407     printf("commnd:request:%s
    ",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
    ",speed,failed); */
    422      fprintf(f,"%d %d %d
    ",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           /*  作为一个读的文件流,为什么要设置成 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.
    ");
    446                        break;
    447                   }
    448           speed+=i;
    449           failed+=j;
    450           bytes+=k;
    451           /* fprintf(stderr,"*Knock* %d %d read=%d
    ",speed,failed,pid); */
    452           if(--clients==0) break;
    453       }
    454       fclose(f);
    455 
    456   printf("
    Speed=%d pages/min, %d bytes/sec.
    Requests: %d susceed, %d failed.
    ",
    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 是 定时器终止时发送给进程的信号
    477           * SIG 是信号名的通用前缀,ALRM是alarm的缩写
    478           * 通常作为长时间操作的超时信号
    479           * 或者提供一种隔一定时间处理某些操作的方式
    480           * 一般是在调用 alarm(t ) t秒后出现
    481           * */
    482     exit(3);
    483  alarm(benchtime);
    484  /* sigcation 和 alarm 设置了一个闹钟,用来定时退出 */
    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
    "); */
    494           failed--;
    495        }
    496        return;
    497     }
    498     s=Socket(host,port);                          
    499     if(s<0) { failed++;continue;} 
    500     /*  申请建立连接失败, fail++
    501      * */
    502     if(rlen!=write(s,req,rlen)) {failed++;close(s);continue;}
    503     /* 无法写入套接字,算是失败吧 ????
    504      * fail++
    505      * */
    506     if(http10==0) 
    507             /*http 0.9 进行关闭操作 ????*/
    508         if(shutdown(s,1))
    509                     /* 1 终止 传送操作 */
    510             { failed++;close(s);continue;}
    511     if(force==0) 
    512             /*  阻塞等待回应
    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
    ",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
    ",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             /* 无符号长整型和负数比较
    43              * 上面这句话有问题, iner_addr 返回一个FFFFFFFF,即-1为错误,在ip地址翻译上 
    44              * 255.255.255.255,这个也就是 为什么不建议使用 inet_addr的原因*/
    45         memcpy(&ad.sin_addr, &inaddr, sizeof(inaddr));
    46 else
    47     {
    48          //   printf("test 4
    ");
    49         hp = gethostbyname(host);
    50         //    printf("test 5
    ");
    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 }

     

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

    最后放一些写个自己的东西

    1. 我学到的字符串更加灵活的应用,尤其是几个以前没有见过的string.h库里的函数

    2. 对http协议有了个初步的了解 : http简明解析

    3. getopt函数的使用的了解

     

      

       

  • 相关阅读:
    《软件需求十步走》读书笔记二
    《软件需求十步走》读书笔记一
    FJUTOJ-周赛2016-12-16
    FJUTOJ-周赛2016-11-25
    网络爬虫
    树链剖分讲解
    HDU 5266 pog loves szh III
    HDU 3518 Boring counting
    HDU 5929 Basic Data Structure
    HDU 1055 Color a Tree
  • 原文地址:https://www.cnblogs.com/dilidingzhi/p/4298096.html
Copyright © 2011-2022 走看看