⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 webclient.c

📁 ACE源码
💻 C
📖 第 1 页 / 共 3 页
字号:
/* webclient.c,v 1.5 2000/09/22 19:30:37 brunsch Exp */
/**************************************************************************
 *                                                                        *
 * 		 Copyright (C) 1995 Silicon Graphics, Inc.		  *
 *									  *
 *  These coded instructions, statements, and computer programs were	  *
 *  developed by SGI for public use.  If any changes are made to this code*
 *  please try to get the changes back to the author.  Feel free to make  *
 *  modifications and changes to the code and release it.		  *
 *									  *
 **************************************************************************/

/* FUZZ: disable check_for_math_include */

#include <thread.h>

#include <stdio.h>

#ifdef WIN32
#include <windows.h>
#include <winsock.h>
#include <time.h>
#include <process.h>
#include <io.h>
#endif /* WIN32 */

#include <errno.h>
#include <signal.h>
#include <stdlib.h>
#include <string.h>

#ifndef WIN32
#include <netdb.h>
#include <unistd.h>
#endif /* WIN32 */

#include <time.h>
#include <math.h>

#ifndef WIN32
#include <sys/param.h>
#endif /* WIN32 */

#include <sys/types.h>

#ifndef WIN32
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/errno.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <sys/wait.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#endif /* WIN32 */

#include <ctype.h>

#include "sysdep.h"
#include "bench.h"

#define _BSD_SIGNALS
#define INFINITY 100000000
#define DEFAULTWWWPORT 80
#define LOG_FILE "logfile"
#ifdef WIN32
#define DEBUG_FILE	"c:/tmp/webstone-debug"
#else
#define DEBUG_FILE	"/tmp/webstone-debug"
#endif /* WIN32 */
#define NCCARGS 4096

/* global variables */

  THREAD FILE	*debugfile = stderr;
  page_list_t *load_file_list; /* actually a dynamic array */

int	amclient = 0;
int	havewebserver = 0;
int	haveproxyserver = 0;
int 	savefile = 0;
NETPORT	portnum = DEFAULTWWWPORT;
int 	timeexpired = 0;
int     debug = 0;
long int	number_of_pages = 0;
char	webmaster[MAXHOSTNAMELEN];
char 	webserver[MAXHOSTNAMELEN];
char	proxyserver[MAXHOSTNAMELEN];


#ifdef WIN32
HANDLE	hSemaphore;
int	CounterSemaphore = 0;   /* counter semaphore for children */
#endif /* WIN32 */

static void ClientThread(void *);

/* used to bypass DNS/YP name resolution for every page */
struct hostent 	webserv_phe, webmast_phe;
struct protoent	webserv_ppe, webmast_ppe; 
unsigned long	webserv_addr, webmast_addr; 
short 		webserv_type, webmast_type;               /* socket type */

/* End of globals */


static void
usage(const char *progname)
{
    returnerr("Usage: %s [-d]  [-w webserver]  [-p port_num]\n",
	progname);
    returnerr("\t[-c masterhost:port]  [-t run_time | -l loops]\n");
    returnerr("\t[-n numclients]  [-R]\n");
    returnerr("\t[-f config_file]  [-u uilfile | url ...]\n");
    errexit("\n");
} /* END usage() */

static void
alarmhandler(void)
{
  /* RECEIVED AN ALARM SIGNAL */
  timeexpired = 1;
} /* END alarmhandler() */

#ifndef WIN32
static void
childhandler(void)
{
  int status;

  /* RECEIVED A SIGNAL THAT A CHILD PROCESS HAS DIED */
  D_PRINTF( "A child process has died\n" );
  while (wait3(&status, WNOHANG, (struct rusage *)0) >= 0)
    {
      /* do nothing */
      ;
    }
} /* END childhandler() */
#endif /* WIN32 */


/* look up the host name and protocol
 * called once by main() since all threads
 * use the same protocol and address
 */

int resolve_addrs(char *host, char *protocol, struct hostent *host_phe, struct protoent *proto_ppe, unsigned long *addr,
	short *type) {
struct hostent *phe;
struct protoent *ppe;

    /* if IP address given, convert to internal form */
    if (host[0] >= '0' && host[0] <= '9') {
	*addr = inet_addr(host);
	if (*addr == INADDR_NONE)
	    return(returnerr("Invalid IP address %s\n", host));
	 
    } else {
	/* look up by name */
	phe = gethostbyname(host);								
	if (phe == NULL)
	{
	    D_PRINTF( "Gethostbyname failed: %s", neterrstr() );
	    return(returnerr("Can't get %s host entry\n", host));
	}
	memcpy(host_phe, phe, sizeof(struct hostent));
	memcpy((char *)addr, phe->h_addr, sizeof(*addr));
    }

    /* Map protocol name to protocol number */
    ppe = getprotobyname(protocol);

    if (ppe == 0)
    {
	D_PRINTF( "protobyname returned %d\n",	ppe );
	return(returnerr("Can't get %s protocol entry\n",protocol));
    }
    memcpy(proto_ppe, ppe, sizeof(struct protoent));

    D_PRINTF( "Protocol number %d\n", ppe->p_proto );

    /* Use protocol to choose a socket type */
    if (strcmp(protocol,"udp") == 0)
    {
	*type = SOCK_DGRAM;
    }
    else
    {
	*type = SOCK_STREAM;
	D_PRINTF( "Choosing SOCK_STREAM %d type %d %s\n", 
	    SOCK_STREAM, *type, neterrstr() );
    }

    return 0;
}

/* connect to a socket given the hostname and protocol */
SOCKET
connectsock(char *host, NETPORT portnum, char *protocol)
 {
  struct sockaddr_in sin;  	/* an Internet endpoint address */
  SOCKET 	s;              /* socket descriptor */
  int 		type;           /* socket type */
  short 	proto;
  int 		returnval;	/* temporary return value */

  D_PRINTF( "Beginning connectsock; host=%s port=%d proto=%s\n", host,
	portnum, protocol );

  sin.sin_family = AF_INET;
  memset((char *)&sin, 0, sizeof(sin));
  D_PRINTF( "Zeroed address structure\n" );

  sin.sin_port = htons(portnum);
  D_PRINTF( "Set port number %d\n", portnum );

  /* get the contact information */
  if (strcmp(host, webserver) == 0) {
      sin.sin_addr.S_ADDR = webserv_addr;
      sin.sin_family = PF_INET;
      proto = webserv_ppe.p_proto;
      type = webserv_type;
  } else if (strcmp(host, webmaster) == 0) {
      sin.sin_addr.S_ADDR = webmast_addr;
      sin.sin_family = PF_INET;
      proto = webmast_ppe.p_proto;
      type = webmast_type;
  } else {
      struct hostent 	host_phe;
      struct protoent	host_ppe;
      unsigned long	host_addr;
      short 		host_type;       /* socket type */

      if (resolve_addrs(host, "tcp", &host_phe, &host_ppe, &host_addr, &host_type))
 	  return returnerr("Can't resolve hostname %s in get()\n", host);
      sin.sin_addr.S_ADDR = host_addr;
      sin.sin_family = PF_INET;
      proto = host_ppe.p_proto;
      type = host_type;
  }

  /* Allocate a socket */
  s = socket(PF_INET, type, proto);
  D_PRINTF( "Socket %d returned %d, %s\n",
	type, s, neterrstr() );
  
  if (BADSOCKET(s))
  {
    D_PRINTF( "Can't create socket: %s\n",neterrstr() );
    return BADSOCKET_VALUE;
  }
  
  /* Connect the socket */
  D_PRINTF( "Trying to connect %d with size %d, %s\n",
	s, sizeof(sin), neterrstr() );
  D_PRINTF( "Address is family %d, port %d, addr %s\n", 
	sin.sin_family, ntohs(sin.sin_port),
	inet_ntoa(sin.sin_addr) );
  
  returnval = connect(s, (struct sockaddr *)&sin, sizeof(sin));
  D_PRINTF( "Connect returned %d, %s\n", 
	returnval, neterrstr() );
  if (returnval < 0)
    {
      D_PRINTF( "Can't connect: %s\n", neterrstr() );
      NETCLOSE(s);
      return BADSOCKET_VALUE;
    }

  /* all done, returning socket descriptor */
  D_PRINTF( "Returning %d from connectsock call\n", s );
  return(s);

} /* END connectsock() */

SOCKET
connecttomaster(char *str)
{
    char   	*tempch;
    SOCKET	sock;
    char	msg[100];
    char 	ConnectStr[100];	/* Fix to handle multiple threads */
    int		tries;

    strcpy(ConnectStr, str);

    /*
     * BREAK UP THE connectstr INTO A HOSTNAME/HOST-IP AND A PORT NUMBER.
     */
    if((tempch = strpbrk(ConnectStr,":")) == NULL)
    {
        /*
         * INCORRECT FORMAT OF ConnectStr. CORRECT FORMAT IS
         * HOSTNAME:PORT OR HOST-IP:PORT
         */
        D_PRINTF( "Incorrect format %s: use hostname:port or ip_addr:port\n",
	 	ConnectStr );
	return(returnerr("Incorrect format %s: use host:port or ip_addr:port\n",
		ConnectStr));
    }

    /*
     * ZERO OUT THE COLON SO WE HAVE TWO STRINGS, THE HOSTNAME AND THE PORT
     */
    *tempch = '\0';
    tempch++;
    
    /* loop here to connect to webmaster - TCP/IP allows no more than 5 
     * connection requests outstanding at once and thus the webmaster may
     * reject a connection if there are a lot of client processes
     */
#define MAXTRIES 30
#define TRYDELAY_SEC	1
    for (tries = 0; tries < MAXTRIES; tries++) {

        sock = connectsock(ConnectStr,(NETPORT)atoi(tempch),"tcp");

	if (!BADSOCKET(sock))
	    break;

	sleep(TRYDELAY_SEC);
    }

    if (BADSOCKET(sock))
    {
	/*  ERROR CONNECTING TO MASTER PROCESS */
	return(returnerr("Could not connect to master process\n"));
    }
	
    /*
     * SIGNAL THE MASTER THAT WE ARE READY TO PROCEED.  WHEN ALL
     * CHILD PROCESSES HAVE CONNECTED AND SENT THIS SIGNAL,
     * THE MASTER WILL ISSUE US A GO SIGNAL.
     */
    if(NETWRITE(sock,READYSTR,READYSTRLEN) != READYSTRLEN)
    {
	return(returnerr("Error sending READY message to master"));
    }
   
    memset(msg,0,GOSTRLEN+1);
    if(NETREAD(sock,msg,GOSTRLEN) != GOSTRLEN)
    {
	D_PRINTF( "Error receiving GO message from master: %s\n", neterrstr()
		);
	return(returnerr("Error receiving GO message from master\n"));
    }

    if(strncmp(GOSTR,msg,GOSTRLEN))
    {
       /*
        * WE RECEIVED A MESSAGE OTHER THAN GO. PRINT IT OUT AND RETURN ERROR
        */
	return(returnerr("Received non-GO message %s\n",msg));
    }

    return(sock);

} /* END connecttomaster() */


static void
accumstats(rqst_timer_t *rqsttimer, page_stats_t *pagestats, stats_t *timestat)
{
    rqst_stats_t	rqststats; 

#define TFMT	"%10u:%10u"
    /*
     * DUMP THE TIMING INFORMATION HERE, OR COMPUTE WHAT YOU WANT TO
     * PRINT OUT LATER.
     */

    D_PRINTF( "Total bytes read: %d \t Body size read: %d\n",
	rqsttimer->totalbytes,
	rqsttimer->bodybytes );

    D_PRINTF( "Enter time:     " TFMT " \t Exit Time:     " TFMT "\n",
	rqsttimer->entertime.tv_sec,
	rqsttimer->entertime.tv_usec,
	rqsttimer->exittime.tv_sec,
	rqsttimer->exittime.tv_usec );
    D_PRINTF( "Before connect: " TFMT " \t After connect: " TFMT "\n",
	rqsttimer->beforeconnect.tv_sec,
	rqsttimer->beforeconnect.tv_usec,
	rqsttimer->afterconnect.tv_sec,
	rqsttimer->afterconnect.tv_usec );
    D_PRINTF( "Before header:  " TFMT " \t After header:  " TFMT "\n",
	rqsttimer->beforeheader.tv_sec,
	rqsttimer->beforeheader.tv_usec,
	rqsttimer->afterheader.tv_sec,
	rqsttimer->afterheader.tv_usec );
    D_PRINTF( "After body:     " TFMT "\n",
	rqsttimer->afterbody.tv_sec,
	rqsttimer->afterbody.tv_usec );

    rqstat_times(&(rqststats), rqsttimer);
    rqstat_sum(&(timestat->rs), &(rqststats));
    rqstat_sum(&(pagestats->rs), &(rqststats));

    if (rqsttimer->page_number != 999)
    {
	timestat->page_numbers[rqsttimer->page_number] += 1;
    }

#undef TFMT
} /* END accumstats */


/* 
 * fetch the set of files that constitute a page
 * 
 * maxcount = the number of files in the WWW page
 * pageval = the number of the WWW page (offset in load_file_list[])
 *	(if -1, use page # 0 - does this still work?)
 *
 * returns the number of files retrieved
 */
static int 
makeload(int maxcount, int pageval, THREAD rqst_timer_t *timerarray, THREAD stats_t *timestat, THREAD SOCKET mastersock, THREAD page_stats_t *page_stats)
{
    int cnt;
    int returnval;
    page_stats_t page_stats_tmp;
    char server[MAXHOSTNAMELEN];

    NETPORT loc_portnum;

    D_PRINTF( "Starting makeload(maxcount %d, pageval %d)\n",
	maxcount, pageval );

    strcpy( server, webserver); /* Put in default value */

    page_stats_init(&page_stats_tmp);
    D_PRINTF( "Page stats initialized\n" );

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -