📄 webclient.c
字号:
/* 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 WIN32HANDLE 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 voidusage(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 voidalarmhandler(void){ /* RECEIVED AN ALARM SIGNAL */ timeexpired = 1;} /* END alarmhandler() */#ifndef WIN32static voidchildhandler(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 */SOCKETconnectsock(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() */SOCKETconnecttomaster(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 voidaccumstats(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 + -