?? webclient.c
字號(hào):
/* 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" );
?? 快捷鍵說(shuō)明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -