netbench_client.c

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
/*内部宏声明*/

#define HOSTNAMESIZE     255
#define PORTBUFSIZE      10
#define TESTNAMESIZE     15
#define MAXSPECDATA      62
#define DO_TCP_STREAM    22
#define TCP_STREAM_ECHO  21
#define NO_CPU_MEASURE   0
#define NO_CPU_RATE      0
#define NO_DELAY         0
#define NO_RCVAVOID      0
#define NO_SNDAVOID      0
#define SIGALRM          14

/*定义变量类型*/
typedef unsigned char       u8;
typedef unsigned short int  u16;
typedef unsigned long  int  u32;

/*for socket create*/
#define DEBUG_INFO
#define INVALID_SOCKET -1
#define SOCKET_ERROR -1
#define SOCKET int
#ifndef AF_NORMAL
#define AF_NORMAL AF_INET
#endif
SOCKET  control_sock = INVALID_SOCKET; 
SOCKET  server_sock = INVALID_SOCKET;

/*error type*/
#define  NOR_ERROR   -1
#define  SOCK_ERROR  -1

/*define send and recv*/
#define SEND_SIZE     1
#define RECV_SIZE     0


/*内部全局变量声明*/
char rem_host_name[HOSTNAMESIZE];
char local_host_name[HOSTNAMESIZE];
char test_name[TESTNAMESIZE];
char rem_port[PORTBUFSIZE];
char local_port[PORTBUFSIZE];
int rem_addr_family;
int local_addr_family;
unsigned int test_time;
unsigned int test_len_ticks;
unsigned int test_size;
char *client_name = NULL;
FILE *where = stdout;
union   netbench_request_struct  netbench_request;
union   netbench_response_struct netbench_response;
char  local_data_port[PORTBUFSIZE];
char  rem_data_port[PORTBUFSIZE];
int
  local_recv_align, /* alignment for local receives  */
  local_send_align, /* alignment for local sends  */
  local_send_offset = 0,
  local_recv_offset = 0,
  remote_recv_align, /* alignment for remote receives */
  remote_send_align, /* alignment for remote sends  */
  remote_send_offset = 0,
  remote_recv_offset = 0;
/*define dirty varibles*/
#ifdef DIRTY
int loc_dirty_count;
int loc_clean_count;
int rem_dirty_count;
int rem_clean_count;
#endif

u16 iteration_min;
u16 iteration_max;
u16 confidence_iteration;
double confidence;
u16  times_up;
/*define send and recv size vairables*/
static int ls_size_req,
           lr_size_req,
           ls_size,
           lr_size,
           rs_size_req,
           rr_size_req,
           rs_size,
           rr_size;
struct timeval    time_begin, time_stop;
float lib_elapsed;
char    libfmt = 'm';     


/*内部结构体声明*/
/*struct addrinfo*/
struct addrinfo {
    int ai_flags;
    int ai_family;
    int ai_socktype;
    int ai_protocol;
    socklen_t ai_addrlen;
    struct sockaddr *ai_addr;
};
struct tcp_stream_request_struct {
  int send_buf_size;
  int recv_buf_size; /* how big does the client want it - the */
   /* receive socket buffer that is */
  int receive_size;   /* how many bytes do we want to receive at one */
   /* time? */
  int recv_alignment; /* what is the alignment of the receive */
   /* buffer? */
  int recv_offset;    /* and at what offset from that alignment? */
  int no_delay;       /* do we disable the nagle algorithm for send */
   /* coalescing? */
  int measure_cpu; /* does the client want server cpu utilization */
   /* measured? */
  float cpu_rate; /* do we know how fast the cpu is already? */
  int test_length; /* how long is the test?  */
  int so_rcvavoid;    /* do we want the remote to avoid copies on */
   /* receives? */
  int so_sndavoid;    /* do we want the remote to avoid send copies? */
  int   dirty_count;    /* how many integers in the receive buffer */
   /* should be made dirty before calling recv? */ 
  int   clean_count;    /* how many integers should be read from the */
   /* recv buffer before calling recv? */
  int   port;           /* the port to which the recv side should bind
      to allow netperf to run through those evil
      firewall things */
  int   ipfamily;       /* the address family of ipaddress */
};

struct tcp_stream_response_struct {
  int recv_buf_size; /* how big does the client want it */
  int receive_size;
  int no_delay;
  int measure_cpu; /* does the client want server cpu */
  int test_length; /* how long is the test?  */
  int send_buf_size;
  int data_port_number; /* connect to me here */
  float cpu_rate;  /* could we measure */
  int so_rcvavoid; /* could the remote avoid receive copies? */
  int so_sndavoid; /* could the remote avoid send copies? */
};

struct tcp_stream_results_struct {
  double         bytes_received;
  unsigned int  recv_calls; 
  float          elapsed_time; /* how long the test ran */
  float          cpu_util; /* -1 if not measured */
  float          serv_dem; /* -1 if not measured */
  int            cpu_method;    /* how was cpu util measured? */
  int            num_cpus;      /* how many CPUs had the remote? */
};

union netbench_request_struct {
  struct {
    int     request_type;
    int     dummy;
    int     test_specific_data[MAXSPECDATA];
  } content;
  double dummy;
};

union netbench_response_struct {
  struct {
    int response_type;
    int serv_errno;
    int test_specific_data[MAXSPECDATA];
  } content;
  double dummy;
};

struct ring_elt {
  struct ring_elt *next;  /* next element in the ring */
  char *buffer_base;      /* in case we have to free it at somepoint */
  char *buffer_ptr;       /* the aligned and offset pointer */
};


/*内部函数声明*/
void set_opt_defaults();
void set_user_opt(int argc, char **argv);
int  getopt(int argc, char **argv);
unsigned int  convert(char *string);
void usage();
void enter_control_sock(char *RemHname, char *RemPort, int RemAf, char * LocHname, char *LocPort, int LocAf);
int  create_control_sock(char *RemHname, char *RemPort, int RemAf, char * LocHname, char *LocPort, int LocAf);
void send_tcp_stream(char *remote_name);

int main(int argc, char **argv)
{
 client_name = *argv[0];
 set_opt_defaults();
 set_user_opt(argc, argv);
 enter_control_sock(rem_host_name,
                 rem_port,
                 rem_addr_family,
                 local_host_name,
                 local_port,
                 local_addr_family);
 if(0 == strcasecmp(test_name, "TCP_STREAM"))
 {
  send_tcp_stream(rem_host_name);
     }
 else if()
 {
   return (0);
 }
 return (0);
}
/*******************************************************
函数功能:设置默认状态下的全局变量
输入参数:无
输出参数:无
作者:
时间:2009/07/31
描述:新生成函数
*********************************************************/
void set_opt_defaults()
{
 strcpy(rem_host_name,"");
 strcpy(local_host_name,"");
 strcpy(test_name,"TCP_STREAM");
 strncpy(rem_port,"12856",PORTBUFSIZE);
 strncpy(local_port,"0",PORTBUFSIZE);
 strncpy(local_data_port, "5000", PORTBUFSIZE);
 strncpy(rem_data_port, "5001", PORTBUFSIZE);
 rem_addr_family = AF_NORMAL;
 local_addr_family = AF_NORMAL;
 test_time = 10;
 test_size = 1024;

 /*set align vairables*/
 local_recv_align  = 8;
 local_send_align  = 8;
 remote_recv_align = 8;
 remote_send_align = 8;

 /*set dirty vairables*/
 #ifdef DIRTY
 loc_dirty_count  = 0;
 loc_clean_count  = 0;
 rem_dirty_count  = 0;
 rem_clean_count  = 0;
 #endif

    /* set some of the vairables for confidence intervals*/
 iteration_min = 1;
    iteration_max = 1;

 /*set send and recv size*/
 ls_size_req = 3*test_size;
 lr_size_req = 3*test_size;
 rs_size_req = 3*test_size;
 rr_size_req = 3*test_size;
 
}
/*******************************************************
函数功能:设置用户传入的全局变量
输入参数:无
输出参数:无
作者:
时间:2009/07/31
描述:新生成函数
*********************************************************/
void set_user_opt(int argc, char **argv)
{
   int c ;
   argc--;
   argv++;
   while((c= getopt(argc, argv)) != EOF)
   {
     switch (c) {
  case '?':
   usage();
   exit(0);
  case 'h':
  case 'H':
   argc--;
   argv++;
         strcpy(rem_host_name,*argv[]);
         break;
  case 'p':
  case 'P':
   argc--;
   argv++;
         strncpy(local_port,*argv[],PORTBUFSIZE);
   break;
  case 'n':
  case 'N':
   argc--;
   argv++;
      strcpy(test_name,*argv[]);
   break;
  case 't':
  case 'T':
   argc--;
   argv++;
         test_time = convert(*argv[]);
   break;
  case 's':
  case 'S':
   argc--;
   argv++;
   test_size = convert(*argv[]);
   break;
  default:
   argc--;
   argv++;
   break;
  }
   }
}
/*******************************************************
函数功能:将一字符串转换为整数
输入参数:无
输出参数:无
作者:
时间:2009/07/31
描述:新生成函数
*********************************************************/
unsigned int  convert(char *string)
{
  unsigned int base;
  base = atoi(string);
  if (strstr(string,"K")) {
    base *= 1024;
  }
  if (strstr(string,"M")) {
    base *= (1024 * 1024);
  }
  if (strstr(string,"G")) {
    base *= (1024 * 1024 * 1024);
  }
  if (strstr(string,"k")) {
    base *= (1000);
  }
  if (strstr(string,"m")) {
    base *= (1000 * 1000);
  }
  if (strstr(string,"g")) {
    base *= (1000 * 1000 * 1000);
  }
  return(base);
}
/*******************************************************
函数功能:打印使用方法
输入参数:无
输出参数:无
作者:
时间:2009/07/31
描述:新生成函数
*********************************************************/
void usage()
{
   fprintf(where,"./%s -H ip_addr -P port_num -n TCP_STREAM -t elapsed_time -s test_size/n",client_name);
   fprintf(where,"each parameter as follows:/n");
   fprintf(where,">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>/n");
   fprintf(where,"H:local host ip address/n");
   fprintf(where,"P:local host port number/n");
   fprintf(where,"n:test type/n");
   fprintf(where,"t:elapsed time/n");
   fprintf(where,"s:each time send size/n");
   fprintf(where,">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>/n");
   fflush(where);
}

/*******************************************************
函数功能:扫描用户输入的参数
输入参数:无
输出参数:无
作者:
时间:2009/07/31
描述:新生成函数
*********************************************************/
int  getopt(int argc, char **argv)
{
 char *PtrArg = *argv[];
 if('-' == *PtrArg)
 {
  return (*(++PtrArg));
 }
 else
 {
  return 0;
 }

}
/*******************************************************
函数功能:调用创建控制端口套接字的入口函数
输入参数:无
输出参数:无
作者:
时间:2009/07/31
描述:新生成函数
*********************************************************/
void enter_control_sock(char *RemHname,
       char *RemPort,
       int RemAf,
       char * LocHname,
       char *LocPort,
       int LocAf)
{
 control_sock = create_control_sock(RemHname,
                                       RemPort,
            RemAf,
            LocHname,
            LocPort,
            LocAf);
 if(control_sock < 0)
 {
        fprintf(where,
     "create_control could not establish the control connection from %s port %s address family %s to %s port %s address family %s/n",
     LocHname,LocPort,inet_ftos(LocAf),
     RemHname,RemPort,inet_ftos(RemAf));
  fflush(where);
        exit(-1);
 }
}
/*******************************************************
函数功能:get address family
输入参数:无
输出参数:address family
作者:
时间:2009/07/31
描述:新生成函数
*********************************************************/
char* inet_ftos(int family)
{
  switch(family) {
  case AF_INET:
    return("AF_INET");
    break;
#if defined(AF_INET6)
  case AF_INET6:
    return("AF_INET6");
    break;
#endif
  default:
    return("AF_NORMAL");
  }
}
/*******************************************************
函数功能:创建控制套接字
输入参数:无
输出参数:无
作者:
时间:2009/07/31
描述:新生成函数
*********************************************************/
int  create_control_sock(char *RemHname,
       char *RemPort,
       int RemAf,
       char * LocHname,
       char *LocPort,
       int LocAf);
{
   int control_sock;
   int ret;
   struct addrinfo  local_info;
   struct addrinfo  remote_info;
   #ifdef DEBUG_INFO
    fprintf(where,
            "establish_control called with host '%s' port '%s' remfam %s/n",
            RemHname,
            RemPort,
            inet_ftos(RemAf));
    fprintf(where,
            "/t/tlocal '%s' port '%s' locfam %s/n",
            LocHname,
            LocPort,
            inet_ftos(LocAf));
    fflush(where);
    #endif
 
 /*do the remote info struct*/
 memset(&remote_info, 0, sizeof(addrinfo));
 remote_info.ai_family = RemAf;
 remote_info.ai_socktype = SOCK_STREAM;
 remote_info.ai_protocol = IPPROTO_TCP;
 remote_info.ai_flags = 0;
 /*get addr info*/
 ret = get_addr_info((char *)RemHname,
                        (char *)RemPort,
                        &remote_info);
 if(ret < 0)
  {
   fprintf(where,"get_addr_info(Remote) failed/n");
   fflush(where);
   return SOCKET_ERROR;
  }

 /*do the local info struct*/
 memset(&local_info, 0, sizeof(addrinfo));
 local_info.ai_family = RemAf;
 local_info.ai_socktype = SOCK_STREAM;
 local_info.ai_protocol = IPPROTO_TCP;
 local_info.ai_flags = 0;
 /*get addr info*/
 ret = get_addr_info((char *)LocHname,
                        (char *)LocPort,
                        &local_info);
 if(ret < 0)
  {
   fprintf(where,"get_addr_info(Local) failed/n");
   fflush(where);
   return SOCKET_ERROR;
  }

 /*ok,start to create control sock*/
 control_sock = socket(local_info.ai_family, SOCK_STREAM, 0);

 if(control_sock < 0)
  {
   fprintf(where,"control_sock socket failed/n");
   fflush(where);
   return SOCKET_ERROR;
  }
 /*bind control_sock to local address*/
 if(bind(control_sock,
  local_info.ai_addr,
  local_info.ai_addrlen) == 0)
  {
  /*successed*/
  #ifdef DEBUG_INFO
  fprintf(where,
  "bound control socket to %s and %s/n",
  LocHname,
  LocPort);
  fflush(where);
  #endif
  }
 else
  {
  /*failed*/
  fprintf(where,
  "bound control socket to %s and %s failed/n",
  LocHname,
  LocPort);
  fflush(where);
  return SOCKET_ERROR;
  }
 
 /*connect remote host*/
 if(connect(control_sock,
  remote_info.ai_addr,
  remote_info.ai_addrlen) == 0)
  {
    /*successed*/
  #ifdef DEBUG_INFO
  fprintf(where,
  "connect control socket to %s and %s/n",
  RemHname,
  RemPort);
  fflush(where);
  #endif
  }
 else
  {
  /*failed*/
  fprintf(where,
  "connect control socket to %s and %s failed/n",
  RemHname,
  RemPort);
  fflush(where);
  return SOCKET_ERROR;
  }
 return (control_sock);
}

/********************************************************************************
函数功能:填充addrinfo结构体,各个结构体的定义及关系如下
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
struct addrinfo {
    int ai_flags;
    int ai_family;
    int ai_socktype;
    int ai_protocol;
    socklen_t ai_addrlen;
    struct sockaddr *ai_addr;
};
info->ai_addrlen = sizeof(struct sockaddr_in) = sizeof(sockaddr)
                                                            _
                                                           | sin_family  <--  AF_INET               _
info->ai_addr <-- sockaddr_in test <-- | sin_port     <--  HostPort              |
                                                           |--------------struct in_addr test |s_addr <-- HostName
                                                           |char sin_zero[8]                            |_
                                                           |_
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
输入参数:无
输出参数:无
作者:
时间:2009/08/1
描述:新生成函数
**********************************************************************************/
int get_addr_info(char *HostName,
                    char *HostPort,
                    struct addrinfo *info)
{
  u16 port;
  struct in_addr      temp_addr;
  struct sockaddr_in*  temp_sock = NULL;

  /*get port number and ip address*/
  if(HostPort != NULL)
   {
     if(is_integer(HostPort))
      {
        port = htons(atoi(HostPort));
      }
   else{
    port = htons(0);
    }
   }
  else
   {
     port = htons(0);
   }
  if(HostName != NULL)
   {
     if(is_address(HostName))
      {
          temp_addr.s_addr = inet_addr(nodename);
      }
   else
    {
        temp_addr.s_addr = htonl(INADDR_ANY);
    }
   
   }
  else
   {
     temp_addr.s_addr = htonl(INADDR_ANY);
   }

   /*fill the info->ai_addr and info->ai_addrlen*/
   info->ai_addrlen = sizeof(struct sockaddr_in);
   info->ai_addr = (struct sockaddr*)malloc(sizeof(sockaddr_in));
   if(info->ai_addr == NULL){
     fprintf(where,"ai_addr malloc failed/n");
  fflush(where);
  free(info->ai_addr);
  return SOCKET_ERROR;
   }
    temp_sock = (struct sockaddr_in*)info->ai_addr;
    temp_sock->sin_family = AF_NORMAL;
 temp_sock->sin_port = port;
 memcpy(&temp_sock->sin_addr, &temp_addr, sizeof(struct in_addr));
 return (0);
  
   
}

/*******************************************************
函数功能:判断输入的参数是否是整数
输入参数:无
输出参数:无
作者:
时间:2009/08/1
描述:新生成函数
*********************************************************/

static int
is_integer(s)
    const char *s;
{
    if (*s == '-' || *s == '+')
 s++;
    if (*s < '0' || '9' < *s)
 return 0;

    s++;
    while ('0' <= *s && *s <= '9')
 s++;

    return (*s == '/0');
}

/*******************************************************
函数功能:判断输入的参数是否是IP地址
输入参数:无
输出参数:无
作者:
时间:2009/08/1
描述:新生成函数
*********************************************************/
static int
is_address(s)
  const char *s;
{
  const static char delimiters[] = {'.', '.', '.', '/0'};
  int i, j;
  int octet;
 
  for (i = 0; i < 4; i++) {
  if (*s == '0' && *(s + 1) != delimiters[i])
   return 0;
  for (j = 0, octet = 0; '0' <= *s && *s <= '9' && j < 3; s++, j++)
   octet = octet * 10 + (*s - '0');
  if (j == 0 || octet > 255 || *s != delimiters[i])
   return 0;
  s++;
  }
 
  return 1;
}

/*******************************************************
函数功能:发送TCP_STREAM报文
输入参数:无
输出参数:无
作者:
时间:2009/08/1
描述:新生成函数
*********************************************************/
void send_tcp_stream(char *remote_host)
{
   float  elapsed_time;
   double     thruput;
   unsigned int nummesg = 0;
   double       bytes_send = 0.0;
   unsigned int send_width = 0;
   int len;
   #ifdef DIRTY
   int *mes_ptr;
   int i;
   #endif
   SOCKET          data_sock;
   struct addrinfo *remote_res;
   struct addrinfo *local_res;
   struct ring_elt *send_ring;
   struct tcp_stream_request_struct *tcp_stream_request;
   struct tcp_stream_response_struct *tcp_stream_response;
   struct tcp_stream_results_struct *tcp_stream_result;
   tcp_stream_request  = (struct tcp_stream_request_struct*)netbench_request.content.test_specific_data;
   tcp_stream_response = (struct tcp_stream_response_struct*)netbench_response.content.test_specific_data;
   tcp_stream_result   = (struct tcp_stream_results_struct*)netbench_response.content.test_specific_data;
   /*complete remote addrinfo and local addrinfo*/
   complete_addrinfos(remote_res,
                      local_res,
                      remote_host,
                      AF_NORMAL,
                      SOCK_STREAM,
                      IPPROTO_TCP,
                      0);
   send_ring = NULL;
   times_up = 0;
   init_stat();

   /*set up data socket*/
   data_sock = create_data_sock(local_res);
   if(data_sock == INVALID_SOCKET)
    {
     printf(where,"send_tcp_stream:data_sock error/n");
  exit(1);
    }
   #ifdef DEBUG_INFO
   printf(where,"data_sock is OK.../n");
   #endif
 /*it is time to malloc send buff*/
   test_size = (test_size > ls_size)?ls_size : test_size;
   if(send_width == 0){
    send_width = (ls_size/test_size) + 1;
 if(send_width == 1) send_width++;
    }
   if(send_ring == NULL){
    send_ring = alloc_ring_buff(send_width,
                          test_size,
                          local_send_align,
                          local_send_offset);
    }

   /*fill request info*/
    netbench_request.content.request_type = DO_TCP_STREAM;
    tcp_stream_request->send_buf_size = rs_size_req;
    tcp_stream_request->recv_buf_size = rr_size_req;
    tcp_stream_request->receive_size = test_size;
    tcp_stream_request->no_delay = NO_DELAY;
    tcp_stream_request->recv_alignment = remote_recv_align;
    tcp_stream_request->recv_offset = remote_recv_offset;
    tcp_stream_request->measure_cpu = NO_CPU_MEASURE;
    tcp_stream_request->cpu_rate = NO_CPU_RATE;
    tcp_stream_request->test_length = test_time;
 tcp_stream_request->so_rcvavoid = NO_RCVAVOID;
    tcp_stream_request->so_sndavoid = NO_SNDAVOID;
 #ifdef DIRTY
 tcp_stream_request->dirty_count       =       rem_dirty_count;
    tcp_stream_request->clean_count       =       rem_clean_count;
 #endif
 tcp_stream_request->port            = atoi(rem_data_port);
    tcp_stream_request->ipfamily        = remote_res->ai_family;

 /*ok,send request*/
 //send_request();
 if(send(control_sock,
      (char *)&netbench_request,
      sizeof(netbench_request),
      &netbench_request) != sizeof(netbench_request)){
      fprintf(where,"request send failure/n");
   fflush(where);
   exit(1);
  }

 /*next step,recv request*/
 //recv_response();

 /**/
 if(!netbench_response.content.serv_errno){
  #ifdef DEBUG_INFO
  fprintf(where,"remote listen done./n");
  fflush(where);
  #endif
  rr_size       = tcp_stream_response->recv_buf_size;
        rs_size       = tcp_stream_response->send_buf_size;
  set_port_num(remote_res,(unsigned short)tcp_stream_response->data_port_number);
  }
 else{
    fprintf(where,
       "netbench: remote error %d",
       netbench_response.content.serv_errno);
          fflush(where);
          exit(1);
  }
 /*connect remote*/
 if(connect(data_sock,
         remote_res->ai_addr,
         remote_res->ai_addrlen) == INVALID_SOCKET){
         fprintf(where,"netbench: send_tcp_stream:connect failed/n");
      fflush(where);
      exit(1);
  }

 /*start timer*/
 start_timer(test_time);
 cpu_start();

 #ifdef DIRTY
 /*initialize the random number*/
 srand((int)getpid());
 #endif


 /*ok, we will start the test*/
 while(!times_up)
  {
  #ifdef DIRTY
  mes_ptr = (int *)(send_ring->buffer_ptr);
  for(i = 0; i < loc_dirty_count; i++){
   *mes_ptr = rand();
   mes_ptr++;
   }
  for(i = 0; i < loc_clean_count; i++){
   loc_dirty_count = *mes_ptr;
   mes_ptr++;
   }
  #endif
  if((len = send(data_sock,
             send_ring->buffer_ptr,
             test_size,
             0)) != test_size){
             /*the test send is bad,must be end of test*/
       printf(where,"netbench:data send error!/n");
       fflush(where);
       exit(1);
   }
  send_ring = send_ring->next;
  }
 /*shut down socket*/
 /**********************************************
 
 int shutdown( int sockfd, int howto) ;
 
 howto选项:
 SHUT_RD 关闭连接的读一半(0)
 SHUT_WR 关闭连接的写这一半(1)
 SHUT_RDWR 关闭连接读读和写(2)
 ************************************************/
 if(shutdowm(data_sock, 1) == SOCKET_ERROR){
  printf(where,"netbench: cannot shutdown tcp stream socket/n");
  fflush(where);
  exit(1);
  }
 recv(data_sock, send_ring->buffer_ptr, test_size, 0);
 cpu_stop(&elapsed_time);

 /*close the socket*/
 close(data_sock);

 /*recv remote results*/
 recv_response();
 if(!netbench_response.content.serv_errno){
  #ifdef DEBUG_INFO
  fprintf(where,"remote results obtained/n");
  fflush(where);
  #endif
  }
 else{
  fprintf(where,"netbench: remote error %d/n",
   netbench_response.content.serv_errno);
  fflush(where);
  exit(1);
  }

 /*calculate the thruput*/
 bytes_send = ntohd(tcp_stream_result->bytes_received);

 thruput = calc_thruput(bytes_send);
  return;
}
/*******************************************************
函数功能:字节转换
输入参数:无
输出参数:无
作者:
时间:2009/08/2
描述:新生成函数
*********************************************************/

double ntohd(double net_double)

{
  /* we rely on things being nicely packed */
  union {
    double whole_thing;
    unsigned int words[2];
    unsigned char bytes[8];
  } conv_rec;

  unsigned char scratch;
  int i;

  /* on those systems where ntohl is a no-op, we want to return the */
  /* original value, unchanged */

  if (ntohl(1L) == 1L) {
    return(net_double);
  }

  conv_rec.whole_thing = net_double;

  /* we know that in the message passing routines that ntohl will have */
  /* been called on the 32 bit quantities. we need to put those back */
  /* the way they belong before we swap */
  conv_rec.words[0] = htonl(conv_rec.words[0]);
  conv_rec.words[1] = htonl(conv_rec.words[1]);
 
  /* now swap */
  for (i=0; i<= 3; i++) {
    scratch = conv_rec.bytes[i];
    conv_rec.bytes[i] = conv_rec.bytes[7-i];
    conv_rec.bytes[7-i] = scratch;
  }
 
  return(conv_rec.whole_thing);
 
}
/*******************************************************
函数功能:进入吞吐量的测试函数
输入参数:无
输出参数:无
作者:
时间:2009/08/2
描述:新生成函数
*********************************************************/
double calc_thruput(double rec_bytes)
{
 
 return(calc_thruput_interval(rec_bytes,lib_elapsed));
}
/*******************************************************
函数功能:吞吐量计算函数
输入参数:无
输出参数:无
作者:
时间:2009/08/2
描述:新生成函数
*********************************************************/
double calc_thruput_interval(double rcv_bytes,double elapsed)
 
{
   double  divisor;
 
   /* We will calculate the thruput in libfmt units/second */
   switch (libfmt) {
   case 'K':
  divisor = 1024.0;
  break;
   case 'M':
  divisor = 1024.0 * 1024.0;
  break;
   case 'G':
  divisor = 1024.0 * 1024.0 * 1024.0;
  break;
   case 'k':
  divisor = 1000.0 / 8.0;
  break;
   case 'm':
  divisor = 1000.0 * 1000.0 / 8.0;
  break;
   case 'g':
  divisor = 1000.0 * 1000.0 * 1000.0 / 8.0;
  break;
  
   default:
  divisor = 1024.0;
   }
  
   return (rcv_bytes / divisor / elapsed);
 
}


/*******************************************************
函数功能:发送请求函数
输入参数:无
输出参数:无
作者:
时间:2009/08/2
描述:新生成函数
*********************************************************/
void send_request()
{
 return;
}
/*******************************************************
函数功能:接收相应函数
输入参数:无
输出参数:无
作者:
时间:2009/08/2
描述:新生成函数
*********************************************************/
void recv_response()
{
   int     tot_bytes_recvd,
           bytes_recvd = 0,
           bytes_left;
   char    *buf = (char *)&netbench_response;
   int     buflen = sizeof(netbench_response);
   int     counter;
   fd_set readfds;
   struct timeval timeout;
   tot_bytes_recvd = 0;
   bytes_left      = buflen;
   /*在一个进程的多端口收发中,需要设置收发套接字集合*/
   FD_ZERO(&readfds);
   FD_SET(control_sock, &readfds);
   timeout.tv_sec = 120;
   timeout.tv_usec = 0;
   if(counter = select(FD_SETSIZE,
                       &readfds,
                       0,
                       0,
                       &timeout)) !=1) {
                       fprintf(where,"netbench:recv_response: no response received.counter %d",counter);
        fflush(where);
        exit(1);
    }

   while ((tot_bytes_recvd != buflen) &&
    ((bytes_recvd = recv(control_sock, buf, bytes_left,0)) > 0 )) {
  tot_bytes_recvd += bytes_recvd;
  buf    += bytes_recvd;
  bytes_left   -= bytes_recvd;
   }

   #ifdef DEBUG_INFO
   fprintf(where,"recv_response: received a %d byte response/n",
     tot_bytes_recvd);
   fflush(where);
   #endif
   if(tot_bytes_recvd < buflen){
      fprintf(stderr,
          "recv_response: partial response received: %d bytes/n",
          tot_bytes_recvd);
      fflush(stderr);
   exit(1);
    }

}

/*******************************************************
函数功能:记录测试的开始时间
输入参数:无
输出参数:无
作者:
时间:2009/08/2
描述:新生成函数
*********************************************************/
void cpu_start()
{
  gettimeofday(&time_begin, NULL);
}
/*******************************************************
函数功能:记录测试的结束时间
输入参数:无
输出参数:无
作者:
时间:2009/08/2
描述:新生成函数
*********************************************************/
void cpu_stop(float *elapsed)
{
  int sec;
  int usec;
  gettimeofday(&time_stop, NULL);
    if (time_stop.tv_usec < time_begin.tv_usec) {
    time_stop.tv_usec += 1000000;
    time_stop.tv_sec  -= 1;
  }
  sec     = time_stop.tv_sec - time_begin.tv_sec;
  usec    = time_stop.tv_usec - time_begin.tv_usec;
  lib_elapsed     = (float)sec + ((float)usec/(float)1000000.0);
 
  *elapsed = lib_elapsed;
}


/*******************************************************
函数功能:启动定时器
输入参数:无
输出参数:无
作者:
时间:2009/08/2
描述:新生成函数
*********************************************************/
void start_timer(unsigned int time)
{
  struct sigaction action;
  #ifdef DEBUG_INFO
  fprintf(where,"About to start a timer for %d seconds./n",time);
  #endif
  action.sa_handler = timer;
  sigemptyset(&(action.sa_mask));
  sigaddset(&(action.sa_mask), SIGALRM);
 
  action.sa_flags = 0;
  if(sigaction(SIGALRM, &action, NULL) < 0){
   fprintf(where,"start timer: error installing alarm handler/n");
 fflush(where);
 exit(1);
   }
  /*start the alarm time*/
  if(alarm(time) != 0){
   fprintf(where,"error starting alarm timer/n");
 fflush(where);
   }
  test_len_ticks = 1;
 
}
/*******************************************************
函数功能:定时启动函数
输入参数:无
输出参数:无
作者:
时间:2009/08/2
描述:新生成函数
*********************************************************/
void timer(int sig)
{
 switch(sig) {
  case SIGINT:
    fprintf(where,"netbench: caught SIGINT/n");
    fflush(where);
    exit(1);
    break;
    case SIGALRM:
    if (--test_len_ticks == 0) {
      /* the test is over */
      if (times_up != 0) {
        fprintf(where,"timer: timer popped with times_up != 0/n");
        fflush(where);
      }
      times_up = 1;
  }
 break;
  }
 return;
}


/*******************************************************
函数功能:分配缓冲区
输入参数:无
输出参数:无
作者:
时间:2009/08/2
描述:新生成函数
*********************************************************/
struct ring_elt *alloc_ring_buff(unsigned int width, unsigned int size, int align, int offset)
{
 
 struct ring_elt *first_link = NULL;
 struct ring_elt *temp_link  = NULL;
 struct ring_elt *prev_link;
 int i;
 int malloc_size;

 malloc_size = size + align + offset;
 assert(width >= 1);

 prev_link = NULL;
 for(i = 1; i <= width; i++){
  temp_link = (struct ring_elt *)malloc(sizeof(struct ring_elt));
 if(temp_link == NULL){
  printf("malloc(%u) failed!/n", sizeof(struct ring_elt));
  free(temp_link);
  exit(1);
  }
 if(i == 1){
  first_link = temp_link;
  prev_link  = temp_link;
  }
 temp_link->buffer_base = (char *)malloc(malloc_size);
 if(temp_link->buffer_base == NULL){
  printf("malloc(%d) failed!/n",malloc_size);
  free(temp_link->buffer_base);
  exit(1);
  }
 temp_link->buffer_ptr += offset;
 //temp_link->next = NULL;
 prev_link->next = temp_link;
 if(i == width){
  temp_link->next = first_link;
  }
 prev_link = temp_link;
  }
 return (first_link);
}

/*******************************************************
函数功能:初始化状态参数
输入参数:无
输出参数:无
作者:
时间:2009/08/2
描述:新生成函数
*********************************************************/
void init_stat()
{
  confidence_iteration = 1;
  confidence = -10.0;
}

/*******************************************************
函数功能:创建传输数据套接字
输入参数:无
输出参数:无
作者:
时间:2009/08/2
描述:新生成函数
*********************************************************/
int create_data_sock(struct addrinfo *res)
{
  SOCKET temp_sock;
  int on = 1;
  temp_sock = socket(res->ai_family,
         res->ai_socktype,
         res->ai_protocol);
  if(temp_sock == INVALID_SOCKET){
       fprintf(where,
     "netbench: create_data_socket: socket: errno %d fam %s type %s prot %s errmsg %s/n",
     inet_ftos(res->ai_family),
     inet_ttos(res->ai_socktype),
     inet_ptos(res->ai_protocol));
    fflush(where);
    exit(1);
   }
  #ifdef DEBUG_INFO
  fprintf(where,"create_data_socket: socket %d obtained.../n", temp_sock);
  fflush(where);
  #endif

  /*set socket buffer size,send and recv*/
  set_sock_buffer(temp_sock, SEND_SIZE, ls_size_req, &ls_size);
  set_sock_buffer(temp_sock, RECV_SIZE, lr_size_req, &lr_size);
  /*set reuse address property*/
  if(setsockopt(temp_sock,
               SOL_SOCKET.
               SO_REUSEADDR,
               &on,
               sizeof(on)) < 0){
               fprintf(where, "netbench:create_data_sock:SO_REUSEADDR failled/n");
    fflush(where);
   }
  /*bind the sock*/
    if (bind(temp_sock,
    res->ai_addr,
    res->ai_addrlen) < 0) {
      fprintf(where,
       "netbench: create_data_socket: data socket bind failed errno %d/n");
      fprintf(where," port: %d/n",get_port_number(res));
      fflush(where);
  }
 return(temp_sock);
}
/**********************************************************
函数功能:获得addrinfo结构体中存储的端口号
输入参数:无
输出参数:无
作者:
时间:2009/08/1
描述:新生成函数
***********************************************************/
static unsigned short get_port_number(struct addrinfo *port_res)
{
  switch(port_res->ai_family){
   case AF_INET:{
  struct sockaddr_in *foo = (struct sockaddr_in *)port_res->ai_addr;
  return (ntohs(foo->sin_port));
  break;
    }
 #if defined(AF_INET6)
     case AF_INET6: {
     struct sockaddr_in6 *foo = (struct sockaddr_in6 *)res->ai_addr;
     return(ntohs(foo->sin6_port));
    break;
      }
  #endif
 default:
  fprintf(where,"Unexpected Address Family of %u/n",port_res->ai_family);
  fflush(where);
  exit(-1);
   }

}
/*******************************************************
函数功能:设置端口号
输入参数:无
输出参数:无
作者:
时间:2009/08/2
描述:新生成函数
*********************************************************/
void set_port_num(struct addrinfo * res, unsigned short port)
{
    switch(res->ai_family) {
     case AF_INET: {
      struct sockaddr_in *foo = (struct sockaddr_in *)res->ai_addr;
      foo->sin_port = htons(port);
     break;
     }
   #if defined(AF_INET6)
      case AF_INET6: {
       struct sockaddr_in6 *foo = (struct sockaddr_in6 *)res->ai_addr;
       foo->sin6_port = htons(port);
       break;
     }
   #endif
  default:
    fprintf(where,
     "Unexpected Address Family of %u/n",res->ai_family);
    fflush(where);
    exit(-1);
  }
}


/*******************************************************
函数功能:设置套接字缓冲区大小
输入参数:无
输出参数:无
作者:
时间:2009/08/1
描述:新生成函数
*********************************************************/
void set_sock_buffer(SOCKET sock_fd, int flag, int req_size, int *rea_size)
{
  int opt_name = (flag == SEND_SIZE)? SO_SNDBUF : SO_RCVBUF;
  socklen_t sock_opt_len;
  if(req_size > 0)
   {
    if(setsockopt(sock_fd, SOL_SOCKET, opt_name,
              (char *)&req_size, sizeof(int)) < 0){
                    fprintf(where, "netbench: set_sock_buffer: %s option:/n",
       (flag == SEND_SIZE) ? "SO_SNDBUF" : "SO_RCVBUF");
      fflush(where);
      exit(1);
     }
  #ifdef DEBUG_INFO
  fprintf(where, "netbench: set_sock_buffer: %s option:/n",
       (flag == SEND_SIZE) ? "SO_SNDBUF" : "SO_RCVBUF");
      fflush(where);
  #endif
   }

  /*get real size*/
  sock_opt_len = sizeof(socklen_t);
  if(getsockopt(sock_fd, SOL_SOCKET, opt_name,
              (char *)rea_size, &sock_opt_len) < 0){
                    fprintf(where, "netbench: set_sock_buffer: %s option:/n",
       (flag == SEND_SIZE) ? "SO_SNDBUF" : "SO_RCVBUF");
      fflush(where);
      *rea_size = -1;
     }
  #ifdef DEBUG_INFO
  fprintf(where, "netbench: set_sock_buffer: %s option:/n",
       (flag == SEND_SIZE) ? "SO_SNDBUF" : "SO_RCVBUF");
      fflush(where);
  #endif
 
}

 

/*******************************************************
函数功能:进入填充本地和远端主机信息
输入参数:无
输出参数:无
作者:
时间:2009/08/1
描述:新生成函数
*********************************************************/
void complete_addrinfos(struct addrinfo*remote_res,
                            struct addrinfo*local_res,
                            char *remote_name,
                            int  family,
                            int type,
                            int protocol,
                            int flag)
{
  /*first,we do remote addrinfo*/
  complete_addrinfo(remote_res, remote_name, family, rem_data_port, type, protocol, flag);
  /*do local addrinfo*/
  complete_addrinfo(local_res, "", family, local_data_port, type, protocol, flag);
 
}
/*******************************************************
函数功能:填充本地和远端主机信息
输入参数:无
输出参数:无
作者:
时间:2009/08/1
描述:新生成函数
*********************************************************/
void complete_addrinfo(struct addrinfo*res,
                       char *remote_name,
                       int family,
                       char *port,
                       int type,
                       int protocol,
                       int flag)
{
   res->ai_family   = family;
   res->ai_socktype = type;
   res->ai_protocol = protocol;
   res->ai_flags    = flag;
   get_addr_info(remote_name, port, res);
  
}

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值