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

📄 ab.c

📁 Apache HTTP Server 是一个功能强大的灵活的与HTTP/1.1相兼容的web服务器.这里给出的是Apache HTTP服务器的源码。
💻 C
📖 第 1 页 / 共 5 页
字号:
static void read_connection(struct connection * c){    apr_size_t r;    apr_status_t status;    char *part;    char respcode[4];		/* 3 digits and null */    r = sizeof(buffer);#ifdef USE_SSL    if (ssl == 1)    {        status = SSL_read (c->ssl, buffer, r);        if (status <= 0) {            good++; c->read = 0;            if (status < 0) printf("SSL read failed - closing connection\n");            close_connection(c);            return;        }    r = status;    }    else {#endif    status = apr_recv(c->aprsock, buffer, &r);    if (APR_STATUS_IS_EAGAIN(status))	return;    else if (r == 0 && APR_STATUS_IS_EOF(status)) {	good++;	close_connection(c);	return;    }    /* catch legitimate fatal apr_recv errors */    else if (status != APR_SUCCESS) {        err_except++; /* XXX: is this the right error counter? */        /* XXX: Should errors here be fatal, or should we allow a         * certain number of them before completely failing? -aaron */        apr_err("apr_recv", status);    }#ifdef USE_SSL    }#endif    totalread += r;    if (c->read == 0) {	c->beginread = apr_time_now();    }    c->read += r;    if (!c->gotheader) {	char *s;	int l = 4;	apr_size_t space = CBUFFSIZE - c->cbx - 1; /* -1 allows for \0 term */	int tocopy = (space < r) ? space : r;#ifdef NOT_ASCII	apr_size_t inbytes_left = space, outbytes_left = space;	status = apr_xlate_conv_buffer(from_ascii, buffer, &inbytes_left,				       c->cbuff + c->cbx, &outbytes_left);	if (status || inbytes_left || outbytes_left) {	    fprintf(stderr, "only simple translation is supported (%d/%u/%u)\n",		    status, inbytes_left, outbytes_left);	    exit(1);	}#else	memcpy(c->cbuff + c->cbx, buffer, space);#endif				/* NOT_ASCII */	c->cbx += tocopy;	space -= tocopy;	c->cbuff[c->cbx] = 0;	/* terminate for benefit of strstr */        if (verbosity >= 2) {	    printf("LOG: header received:\n%s\n", c->cbuff);	}	s = strstr(c->cbuff, "\r\n\r\n");	/*	 * this next line is so that we talk to NCSA 1.5 which blatantly	 * breaks the http specifaction	 */	if (!s) {	    s = strstr(c->cbuff, "\n\n");	    l = 2;	}	if (!s) {	    /* read rest next time */	    if (space) {		return;	    }	    else {		/* header is in invalid or too big - close connection */                apr_pollfd_t remove_pollfd;                remove_pollfd.desc_type = APR_POLL_SOCKET;                remove_pollfd.desc.s = c->aprsock;                apr_pollset_remove(readbits, &remove_pollfd);		apr_socket_close(c->aprsock);		err_response++;		if (bad++ > 10) {		    err("\nTest aborted after 10 failures\n\n");		}		start_connect(c);	    }	}	else {	    /* have full header */	    if (!good) {		/*		 * this is first time, extract some interesting info		 */		char *p, *q;		p = strstr(c->cbuff, "Server:");		q = servername;		if (p) {		    p += 8;		    while (*p > 32)			*q++ = *p++;		}		*q = 0;	    }	    /*	     * XXX: this parsing isn't even remotely HTTP compliant... but in	     * the interest of speed it doesn't totally have to be, it just	     * needs to be extended to handle whatever servers folks want to	     * test against. -djg	     */	    /* check response code */	    part = strstr(c->cbuff, "HTTP");	/* really HTTP/1.x_ */            if (part && strlen(part) > strlen("HTTP/1.x_")) {                strncpy(respcode, (part + strlen("HTTP/1.x_")), 3);                respcode[3] = '\0';            }            else {                strcpy(respcode, "500");            }	    if (respcode[0] != '2') {		err_response++;		if (verbosity >= 2)		    printf("WARNING: Response code not 2xx (%s)\n", respcode);	    }	    else if (verbosity >= 3) {		printf("LOG: Response code = %s\n", respcode);	    }	    c->gotheader = 1;	    *s = 0;		/* terminate at end of header */	    if (keepalive &&		(strstr(c->cbuff, "Keep-Alive")		 || strstr(c->cbuff, "keep-alive"))) {	/* for benefit of MSIIS */		char *cl;		cl = strstr(c->cbuff, "Content-Length:");		/* handle NCSA, which sends Content-length: */		if (!cl)		    cl = strstr(c->cbuff, "Content-length:");		if (cl) {		    c->keepalive = 1;		    c->length = atoi(cl + 16);		}	    }	    c->bread += c->cbx - (s + l - c->cbuff) + r - tocopy;	    totalbread += c->bread;	}    }    else {	/* outside header, everything we have read is entity body */	c->bread += r;	totalbread += r;    }    if (c->keepalive && (c->bread >= c->length)) {	/* finished a keep-alive connection */	good++;	/* save out time */	if (good == 1) {	    /* first time here */	    doclen = c->bread;	}	else if (c->bread != doclen) {	    bad++;	    err_length++;	}	if (done < requests) {	    struct data s;	    doneka++;	    if (done && heartbeatres && !(done % heartbeatres)) {		fprintf(stderr, "Completed %ld requests\n", done);		fflush(stderr);	    }	    c->done = apr_time_now();	    s.read = c->read;	    s.starttime = c->start;	    s.ctime = (c->connect - c->start) / 1000;	    s.waittime = (c->beginread - c->endwrite) / 1000;	    s.time = (c->done - c->start) / 1000;	    stats[done++] = s;	}	c->keepalive = 0;	c->length = 0;	c->gotheader = 0;	c->cbx = 0;	c->read = c->bread = 0;	c->start = c->connect = apr_time_now();	/* zero connect time with keep-alive */	write_request(c);    }}/* --------------------------------------------------------- *//* run the tests */static void test(void){    apr_time_t now;    apr_int16_t rv;    long i;    apr_status_t status;#ifdef NOT_ASCII    apr_size_t inbytes_left, outbytes_left;#endif    if (isproxy) {	connecthost = apr_pstrdup(cntxt, proxyhost);	connectport = proxyport;    }    else {	connecthost = apr_pstrdup(cntxt, hostname);	connectport = port;    }    if (!use_html) {	printf("Benchmarking %s ", hostname);	if (isproxy)	    printf("[through %s:%d] ", proxyhost, proxyport);	printf("(be patient)%s",	       (heartbeatres ? "\n" : "..."));	fflush(stdout);    }    now = apr_time_now();    con = calloc(concurrency * sizeof(struct connection), 1);        stats = calloc(requests * sizeof(struct data), 1);    if ((status = apr_pollset_create(&readbits, concurrency, cntxt, 0)) != APR_SUCCESS) {        apr_err("apr_pollset_create failed", status);    }    /* setup request */    if (posting <= 0) {	sprintf(request, "%s %s HTTP/1.0\r\n"		"User-Agent: ApacheBench/%s\r\n"		"%s" "%s" "%s"		"Host: %s%s\r\n"		"Accept: */*\r\n"		"%s" "\r\n",		(posting == 0) ? "GET" : "HEAD",		(isproxy) ? fullurl : path,		AP_AB_BASEREVISION,		keepalive ? "Connection: Keep-Alive\r\n" : "",		cookie, auth, host_field, colonhost, hdrs);    }    else {	sprintf(request, "POST %s HTTP/1.0\r\n"		"User-Agent: ApacheBench/%s\r\n"		"%s" "%s" "%s"		"Host: %s%s\r\n"		"Accept: */*\r\n"		"Content-length: %" APR_SIZE_T_FMT "\r\n"		"Content-type: %s\r\n"		"%s"		"\r\n",		(isproxy) ? fullurl : path,		AP_AB_BASEREVISION,		keepalive ? "Connection: Keep-Alive\r\n" : "",		cookie, auth,		host_field, colonhost, postlen,		(content_type[0]) ? content_type : "text/plain", hdrs);    }    if (verbosity >= 2)	printf("INFO: POST header == \n---\n%s\n---\n", request);    reqlen = strlen(request);    /*     * Combine headers and (optional) post file into one contineous buffer     */    if (posting == 1) {	char *buff = malloc(postlen + reqlen + 1);        if (!buff) {            fprintf(stderr, "error creating request buffer: out of memory\n");            return;        }	strcpy(buff, request);	strcpy(buff + reqlen, postdata);	request = buff;    }#ifdef NOT_ASCII    inbytes_left = outbytes_left = reqlen;    status = apr_xlate_conv_buffer(to_ascii, request, &inbytes_left,				   request, &outbytes_left);    if (status || inbytes_left || outbytes_left) {	fprintf(stderr, "only simple translation is supported (%d/%u/%u)\n",		status, inbytes_left, outbytes_left);	exit(1);    }#endif				/* NOT_ASCII */    /* This only needs to be done once */#ifdef USE_SSL    if (ssl != 1)#endif    if ((rv = apr_sockaddr_info_get(&destsa, connecthost, APR_UNSPEC, connectport, 0, cntxt))	!= APR_SUCCESS) {	char buf[120];	apr_snprintf(buf, sizeof(buf),		     "apr_sockaddr_info_get() for %s", connecthost);	apr_err(buf, rv);    }    /* ok - lets start */    start = apr_time_now();    /* initialise lots of requests */    for (i = 0; i < concurrency; i++) {	con[i].socknum = i;	start_connect(&con[i]);    }    while (done < requests) {	apr_int32_t n;	apr_int32_t timed;        const apr_pollfd_t *pollresults;	/* check for time limit expiry */	now = apr_time_now();	timed = (apr_int32_t)apr_time_sec(now - start);	if (tlimit && timed >= tlimit) {	    requests = done;	/* so stats are correct */	    break;		/* no need to do another round */	}	n = concurrency;#ifdef USE_SSL        if (ssl == 1)            status = APR_SUCCESS;        else#endif	status = apr_pollset_poll(readbits, aprtimeout, &n, &pollresults);	if (status != APR_SUCCESS)	    apr_err("apr_poll", status);	if (!n) {	    err("\nServer timed out\n\n");	}	for (i = 0; i < n; i++) {            const apr_pollfd_t *next_fd = &(pollresults[i]);            struct connection *c = next_fd->client_data;	    /*	     * If the connection isn't connected how can we check it?	     */	    if (c->state == STATE_UNCONNECTED)		continue;#ifdef USE_SSL            if (ssl == 1)                rv = APR_POLLIN;            else#endif            rv = next_fd->rtnevents;	    /*	     * Notes: APR_POLLHUP is set after FIN is received on some	     * systems, so treat that like APR_POLLIN so that we try to read	     * again.	     *	     * Some systems return APR_POLLERR with APR_POLLHUP.  We need to	     * call read_connection() for APR_POLLHUP, so check for	     * APR_POLLHUP first so that a closed connection isn't treated	     * like an I/O error.  If it is, we never figure out that the	     * connection is done and we loop here endlessly calling	     * apr_poll().	     */	    if ((rv & APR_POLLIN) || (rv & APR_POLLPRI) || (rv & APR_POLLHUP))		read_connection(c);	    if ((rv & APR_POLLERR) || (rv & APR_POLLNVAL)) {		bad++;		err_except++;		start_connect(c);		continue;	    }	    if (rv & APR_POLLOUT) {                if (c->state == STATE_CONNECTING) {                    apr_pollfd_t remove_pollfd;                    rv = apr_connect(c->aprsock, destsa);                    remove_pollfd.desc_type = APR_POLL_SOCKET;                    remove_pollfd.desc.s = c->aprsock;                    apr_pollset_remove(readbits, &remove_pollfd);                    if (rv != APR_SUCCESS) {                        apr_socket_close(c->aprsock);                        err_conn++;                        if (bad++ > 10) {                            fprintf(stderr,                                    "\nTest aborted after 10 failures\n\n");                            apr_err("apr_connect()", rv);                        }                        c->state = STATE_UNCONNECTED;                        start_connect(c);                        continue;                    }                    else {                        c->state = STATE_CONNECTED;                        write_request(c);                    }                }                else {                    write_request(c);                }            }	    /*	     * When using a select based poll every time we check the bits	     * are reset. In 1.3's ab we copied the FD_SET's each time	     * through, but here we're going to check the state and if the	     * connection is in STATE_READ or STATE_CONNECTING we'll add the	     * socket back in as APR_POLLIN.	     */#ifdef USE_SSL            if (ssl != 1)#endif                if (c->state == STATE_READ) {                    apr_pollfd_t new_pollfd;                    new_pollfd.desc_type = APR_POLL_SOCKET;                    new_pollfd.reqevents = APR_POLLIN;                    new_pollfd.desc.s = c->aprsock;

⌨️ 快捷键说明

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