2
This commit is contained in:
BIN
exp1/badcount
BIN
exp1/badcount
Binary file not shown.
@@ -4,44 +4,46 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
|
|
||||||
void *increase(void *vargp);
|
void *increase(void *vargp);
|
||||||
void *decrease(void *vargp);
|
void *decrease(void *vargp);
|
||||||
int cnt = 0;
|
int cnt = 0;
|
||||||
|
|
||||||
|
int main()
|
||||||
int main(int argc, char **argv)
|
|
||||||
{
|
{
|
||||||
unsigned int niters;
|
unsigned int niters;
|
||||||
pthread_t t1,t2;
|
pthread_t t1, t2;
|
||||||
|
|
||||||
if (argc != 2)
|
niters = 10;
|
||||||
{
|
|
||||||
printf("Usage: %s <niters>\n", argv[0]);
|
|
||||||
exit(2);
|
|
||||||
}
|
|
||||||
niters = atoll(argv[1]);
|
|
||||||
|
|
||||||
pthread_create(&t1,NULL,increase,(void *)niters);
|
for (int i = 0; i < 10; i++)
|
||||||
pthread_create(&t2,NULL,decrease,(void *)niters);
|
{
|
||||||
pthread_join(t1,NULL);
|
printf("niters=%d\n", niters);
|
||||||
pthread_join(t2,NULL);
|
for (int j = 0; j < 20; j++)
|
||||||
|
{
|
||||||
|
pthread_create(&t1, NULL, increase, (void *)niters);
|
||||||
|
pthread_create(&t2, NULL, decrease, (void *)niters);
|
||||||
|
pthread_join(t1, NULL);
|
||||||
|
pthread_join(t2, NULL);
|
||||||
|
|
||||||
if (cnt != 0)
|
if (cnt != 0)
|
||||||
{
|
{
|
||||||
printf("Error! cnt=%d\n", cnt);
|
printf("Error! cnt=%d\n", cnt);
|
||||||
}
|
exit(1);
|
||||||
else
|
}
|
||||||
{
|
else
|
||||||
printf("Correct! cnt=%d\n", cnt);
|
{
|
||||||
|
printf("Correct! cnt=%d\n", cnt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
niters *= 10;
|
||||||
}
|
}
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void *increase(void *vargp)
|
void *increase(void *vargp)
|
||||||
{
|
{
|
||||||
unsigned i ,niters = (unsigned int)vargp;
|
unsigned i, niters = (unsigned int)vargp;
|
||||||
for ( i = 0; i < niters; i++)
|
for (i = 0; i < niters; i++)
|
||||||
{
|
{
|
||||||
cnt++;
|
cnt++;
|
||||||
}
|
}
|
||||||
@@ -51,7 +53,7 @@ void *increase(void *vargp)
|
|||||||
void *decrease(void *vargp)
|
void *decrease(void *vargp)
|
||||||
{
|
{
|
||||||
unsigned i, niters = (unsigned int)vargp;
|
unsigned i, niters = (unsigned int)vargp;
|
||||||
for ( i = 0; i < niters; i++)
|
for (i = 0; i < niters; i++)
|
||||||
{
|
{
|
||||||
cnt--;
|
cnt--;
|
||||||
}
|
}
|
||||||
|
|||||||
BIN
exp1/task62
BIN
exp1/task62
Binary file not shown.
BIN
server-exp/cgi-bin/add
Executable file
BIN
server-exp/cgi-bin/add
Executable file
Binary file not shown.
27
server-exp/cgi-bin/add.c
Normal file
27
server-exp/cgi-bin/add.c
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#define MAXLINE 8192
|
||||||
|
|
||||||
|
int main(void) {
|
||||||
|
char *buf, *p;
|
||||||
|
char content[MAXLINE];
|
||||||
|
int n1=0, n2=0;
|
||||||
|
|
||||||
|
/* Extract the two arguments from standard input */
|
||||||
|
scanf("%d&%d", &n1, &n2);
|
||||||
|
|
||||||
|
/* Make the response body */
|
||||||
|
sprintf(content, "Welcome to add.com: ");
|
||||||
|
sprintf(content, "%sTHE Internet addition portal.\r\n<p>", content);
|
||||||
|
sprintf(content, "%sThe answer is: %d + %d = %d\r\n<p>",
|
||||||
|
content, n1, n2, n1 + n2);
|
||||||
|
sprintf(content, "%sThanks for visiting!\r\n", content);
|
||||||
|
|
||||||
|
/* Generate the HTTP response */
|
||||||
|
printf("Content-length: %d\r\n", (int) strlen(content));
|
||||||
|
printf("Content-type: text/html\r\n\r\n");
|
||||||
|
printf("%s", content);
|
||||||
|
fflush(stdout);
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
242
server-exp/common.c
Normal file
242
server-exp/common.c
Normal file
@@ -0,0 +1,242 @@
|
|||||||
|
/* $begin common.c */
|
||||||
|
|
||||||
|
#include "common.h"
|
||||||
|
|
||||||
|
|
||||||
|
/*********************************************************************
|
||||||
|
* The Rio package - robust I/O functions
|
||||||
|
**********************************************************************/
|
||||||
|
/*
|
||||||
|
* rio_readn - robustly read n bytes (unbuffered)
|
||||||
|
*/
|
||||||
|
/* $begin rio_readn */
|
||||||
|
ssize_t rio_readn(int fd, void *usrbuf, size_t n)
|
||||||
|
{
|
||||||
|
size_t nleft = n;
|
||||||
|
ssize_t nread;
|
||||||
|
char *bufp = usrbuf;
|
||||||
|
|
||||||
|
while (nleft > 0) {
|
||||||
|
if ((nread = read(fd, bufp, nleft)) < 0) {
|
||||||
|
if (errno == EINTR) /* interrupted by sig handler return */
|
||||||
|
nread = 0; /* and call read() again */
|
||||||
|
else
|
||||||
|
return -1; /* errno set by read() */
|
||||||
|
}
|
||||||
|
else if (nread == 0)
|
||||||
|
break; /* EOF */
|
||||||
|
nleft -= nread;
|
||||||
|
bufp += nread;
|
||||||
|
}
|
||||||
|
return (n - nleft); /* return >= 0 */
|
||||||
|
}
|
||||||
|
/* $end rio_readn */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* rio_writen - robustly write n bytes (unbuffered)
|
||||||
|
*/
|
||||||
|
/* $begin rio_writen */
|
||||||
|
ssize_t rio_writen(int fd, void *usrbuf, size_t n)
|
||||||
|
{
|
||||||
|
size_t nleft = n;
|
||||||
|
ssize_t nwritten;
|
||||||
|
char *bufp = usrbuf;
|
||||||
|
|
||||||
|
while (nleft > 0) {
|
||||||
|
if ((nwritten = write(fd, bufp, nleft)) <= 0) {
|
||||||
|
if (errno == EINTR) /* interrupted by sig handler return */
|
||||||
|
nwritten = 0; /* and call write() again */
|
||||||
|
else
|
||||||
|
return -1; /* errorno set by write() */
|
||||||
|
}
|
||||||
|
nleft -= nwritten;
|
||||||
|
bufp += nwritten;
|
||||||
|
}
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
/* $end rio_writen */
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* rio_read - This is a wrapper for the Unix read() function that
|
||||||
|
* transfers min(n, rio_cnt) bytes from an internal buffer to a user
|
||||||
|
* buffer, where n is the number of bytes requested by the user and
|
||||||
|
* rio_cnt is the number of unread bytes in the internal buffer. On
|
||||||
|
* entry, rio_read() refills the internal buffer via a call to
|
||||||
|
* read() if the internal buffer is empty.
|
||||||
|
*/
|
||||||
|
/* $begin rio_read */
|
||||||
|
static ssize_t rio_read(rio_t *rp, char *usrbuf, size_t n)
|
||||||
|
{
|
||||||
|
int cnt;
|
||||||
|
|
||||||
|
while (rp->rio_cnt <= 0) { /* refill if buf is empty */
|
||||||
|
rp->rio_cnt = read(rp->rio_fd, rp->rio_buf,
|
||||||
|
sizeof(rp->rio_buf));
|
||||||
|
if (rp->rio_cnt < 0) {
|
||||||
|
if (errno != EINTR) /* interrupted by sig handler return */
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
else if (rp->rio_cnt == 0) /* EOF */
|
||||||
|
return 0;
|
||||||
|
else
|
||||||
|
rp->rio_bufptr = rp->rio_buf; /* reset buffer ptr */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Copy min(n, rp->rio_cnt) bytes from internal buf to user buf */
|
||||||
|
cnt = n;
|
||||||
|
if (rp->rio_cnt < n)
|
||||||
|
cnt = rp->rio_cnt;
|
||||||
|
memcpy(usrbuf, rp->rio_bufptr, cnt);
|
||||||
|
rp->rio_bufptr += cnt;
|
||||||
|
rp->rio_cnt -= cnt;
|
||||||
|
return cnt;
|
||||||
|
}
|
||||||
|
/* $end rio_read */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* rio_readinitb - Associate a descriptor with a read buffer and reset buffer
|
||||||
|
*/
|
||||||
|
/* $begin rio_readinitb */
|
||||||
|
void rio_readinitb(rio_t *rp, int fd)
|
||||||
|
{
|
||||||
|
rp->rio_fd = fd;
|
||||||
|
rp->rio_cnt = 0;
|
||||||
|
rp->rio_bufptr = rp->rio_buf;
|
||||||
|
}
|
||||||
|
/* $end rio_readinitb */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* rio_readnb - Robustly read n bytes (buffered)
|
||||||
|
*/
|
||||||
|
/* $begin rio_readnb */
|
||||||
|
ssize_t rio_readnb(rio_t *rp, void *usrbuf, size_t n)
|
||||||
|
{
|
||||||
|
size_t nleft = n;
|
||||||
|
ssize_t nread;
|
||||||
|
char *bufp = usrbuf;
|
||||||
|
|
||||||
|
while (nleft > 0) {
|
||||||
|
if ((nread = rio_read(rp, bufp, nleft)) < 0) {
|
||||||
|
if (errno == EINTR) /* interrupted by sig handler return */
|
||||||
|
nread = 0; /* call read() again */
|
||||||
|
else
|
||||||
|
return -1; /* errno set by read() */
|
||||||
|
}
|
||||||
|
else if (nread == 0)
|
||||||
|
break; /* EOF */
|
||||||
|
nleft -= nread;
|
||||||
|
bufp += nread;
|
||||||
|
}
|
||||||
|
return (n - nleft); /* return >= 0 */
|
||||||
|
}
|
||||||
|
/* $end rio_readnb */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* rio_readlineb - robustly read a text line (buffered)
|
||||||
|
*/
|
||||||
|
/* $begin rio_readlineb */
|
||||||
|
ssize_t rio_readlineb(rio_t *rp, void *usrbuf, size_t maxlen)
|
||||||
|
{
|
||||||
|
int n, rc;
|
||||||
|
char c, *bufp = usrbuf;
|
||||||
|
|
||||||
|
for (n = 1; n < maxlen; n++) {
|
||||||
|
if ((rc = rio_read(rp, &c, 1)) == 1) {
|
||||||
|
*bufp++ = c;
|
||||||
|
if (c == '\n')
|
||||||
|
break;
|
||||||
|
} else if (rc == 0) {
|
||||||
|
if (n == 1)
|
||||||
|
return 0; /* EOF, no data read */
|
||||||
|
else
|
||||||
|
break; /* EOF, some data was read */
|
||||||
|
} else
|
||||||
|
return -1; /* error */
|
||||||
|
}
|
||||||
|
*bufp = 0;
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
/* $end rio_readlineb */
|
||||||
|
|
||||||
|
/**********************************
|
||||||
|
* Wrappers for robust I/O routines
|
||||||
|
**********************************/
|
||||||
|
|
||||||
|
|
||||||
|
/********************************
|
||||||
|
* Client/server helper functions
|
||||||
|
********************************/
|
||||||
|
/*
|
||||||
|
* open_client_sock - open connection to server at <hostname, port>
|
||||||
|
* and return a socket descriptor ready for reading and writing.
|
||||||
|
* Returns -1 and sets errno on Unix error.
|
||||||
|
* Returns -2 and sets h_errno on DNS (gethostbyname) error.
|
||||||
|
*/
|
||||||
|
/* $begin open_client_sock */
|
||||||
|
int open_client_sock(char *hostname, int port)
|
||||||
|
{
|
||||||
|
int client_sock;
|
||||||
|
struct hostent *hp;
|
||||||
|
struct sockaddr_in serveraddr;
|
||||||
|
|
||||||
|
if ((client_sock = socket(AF_INET, SOCK_STREAM, 0)) < 0)
|
||||||
|
return -1; /* check errno for cause of error */
|
||||||
|
|
||||||
|
/* Fill in the server's IP address and port */
|
||||||
|
if ((hp = gethostbyname(hostname)) == NULL)
|
||||||
|
return -2; /* check h_errno for cause of error */
|
||||||
|
bzero((char *) &serveraddr, sizeof(serveraddr));
|
||||||
|
serveraddr.sin_family = AF_INET;
|
||||||
|
bcopy((char *)hp->h_addr_list[0],
|
||||||
|
(char *)&serveraddr.sin_addr.s_addr, hp->h_length);
|
||||||
|
serveraddr.sin_port = htons(port);
|
||||||
|
|
||||||
|
/* Establish a connection with the server */
|
||||||
|
if (connect(client_sock, (SA *) &serveraddr, sizeof(serveraddr)) < 0)
|
||||||
|
return -1;
|
||||||
|
return client_sock;
|
||||||
|
}
|
||||||
|
/* $end open_client_sock */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* open_listen_sock - open and return a listening socket on port
|
||||||
|
* Returns -1 and sets errno on Unix error.
|
||||||
|
*/
|
||||||
|
/* $begin open_listen_sock */
|
||||||
|
int open_listen_sock(int port)
|
||||||
|
{
|
||||||
|
int listen_sock, optval=1;
|
||||||
|
struct sockaddr_in serveraddr;
|
||||||
|
|
||||||
|
/* Create a socket descriptor */
|
||||||
|
if ((listen_sock = socket(AF_INET, SOCK_STREAM, 0)) < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
/* Eliminates "Address already in use" error from bind. */
|
||||||
|
if (setsockopt(listen_sock, SOL_SOCKET, SO_REUSEADDR,
|
||||||
|
(const void *)&optval , sizeof(int)) < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
/* Listen_sock will be an endpoint for all requests to port
|
||||||
|
on any IP address for this host */
|
||||||
|
bzero((char *) &serveraddr, sizeof(serveraddr));
|
||||||
|
serveraddr.sin_family = AF_INET;
|
||||||
|
serveraddr.sin_addr.s_addr = htonl(INADDR_ANY);
|
||||||
|
serveraddr.sin_port = htons((unsigned short)port);
|
||||||
|
if (bind(listen_sock, (SA *)&serveraddr, sizeof(serveraddr)) < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
/* Make it a listening socket ready to accept connection requests */
|
||||||
|
if (listen(listen_sock, LISTENQ) < 0)
|
||||||
|
return -1;
|
||||||
|
return listen_sock;
|
||||||
|
}
|
||||||
|
/* $end open_listen_sock */
|
||||||
|
|
||||||
|
|
||||||
|
/* $end wrapper.c */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
76
server-exp/common.h
Normal file
76
server-exp/common.h
Normal file
@@ -0,0 +1,76 @@
|
|||||||
|
/* $begin common.h */
|
||||||
|
#ifndef __COMMON_H__
|
||||||
|
#define __COMMON_H__
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <setjmp.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/wait.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <sys/mman.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <math.h>
|
||||||
|
#include <pthread.h>
|
||||||
|
#include <semaphore.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <netdb.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
#include <limits.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/ipc.h>
|
||||||
|
#include <sys/msg.h>
|
||||||
|
#include <sys/shm.h>
|
||||||
|
#include <sys/sem.h>
|
||||||
|
|
||||||
|
/* Default file permissions are DEF_MODE & ~DEF_UMASK */
|
||||||
|
/* $begin createmasks */
|
||||||
|
#define DEF_MODE S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH
|
||||||
|
#define DEF_UMASK S_IWGRP|S_IWOTH
|
||||||
|
/* $end createmasks */
|
||||||
|
|
||||||
|
/* Simplifies calls to bind(), connect(), and accept() */
|
||||||
|
/* $begin sockaddrdef */
|
||||||
|
typedef struct sockaddr SA;
|
||||||
|
/* $end sockaddrdef */
|
||||||
|
|
||||||
|
/* Persistent state for the robust I/O (Rio) package */
|
||||||
|
/* $begin rio_t */
|
||||||
|
#define RIO_BUFSIZE 8192
|
||||||
|
typedef struct {
|
||||||
|
int rio_fd; /* descriptor for this internal buf */
|
||||||
|
int rio_cnt; /* unread bytes in internal buf */
|
||||||
|
char *rio_bufptr; /* next unread byte in internal buf */
|
||||||
|
char rio_buf[RIO_BUFSIZE]; /* internal buffer */
|
||||||
|
} rio_t;
|
||||||
|
/* $end rio_t */
|
||||||
|
|
||||||
|
/* External variables */
|
||||||
|
extern int h_errno; /* defined by BIND for DNS errors */
|
||||||
|
extern char **environ; /* defined by libc */
|
||||||
|
|
||||||
|
/* Misc constants */
|
||||||
|
#define MAXLINE 8192 /* max text line length */
|
||||||
|
#define MAXBUF 8192 /* max I/O buffer size */
|
||||||
|
#define LISTENQ 1024 /* second argument to listen() */
|
||||||
|
|
||||||
|
/* Rio (Robust I/O) package */
|
||||||
|
ssize_t rio_readn(int fd, void *usrbuf, size_t n);
|
||||||
|
ssize_t rio_writen(int fd, void *usrbuf, size_t n);
|
||||||
|
void rio_readinitb(rio_t *rp, int fd);
|
||||||
|
ssize_t rio_readnb(rio_t *rp, void *usrbuf, size_t n);
|
||||||
|
ssize_t rio_readlineb(rio_t *rp, void *usrbuf, size_t maxlen);
|
||||||
|
|
||||||
|
/* Client/server helper functions */
|
||||||
|
int open_client_sock(char *hostname, int portno);
|
||||||
|
int open_listen_sock(int portno);
|
||||||
|
|
||||||
|
#endif /* __COMMON_H__ */
|
||||||
|
/* $end common.h */
|
||||||
BIN
server-exp/example.jpg
Normal file
BIN
server-exp/example.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 189 KiB |
BIN
server-exp/favicon.ico
Normal file
BIN
server-exp/favicon.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 16 KiB |
BIN
server-exp/ftpc
Executable file
BIN
server-exp/ftpc
Executable file
Binary file not shown.
109
server-exp/ftpc.c
Normal file
109
server-exp/ftpc.c
Normal file
@@ -0,0 +1,109 @@
|
|||||||
|
#include "common.h"
|
||||||
|
|
||||||
|
typedef struct ftp_file
|
||||||
|
{
|
||||||
|
char cmd[MAXLINE]; // FTP命令
|
||||||
|
char filename[MAXLINE]; // 文件名参数
|
||||||
|
char fileSize[MAXLINE]; // 文件大小参数
|
||||||
|
} ftp_file_t;
|
||||||
|
|
||||||
|
|
||||||
|
int main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
int client_sock, port;
|
||||||
|
char *host, buf[MAXLINE];
|
||||||
|
rio_t rio;
|
||||||
|
|
||||||
|
if (argc != 3) {
|
||||||
|
fprintf(stderr, "usage: %s <host><port>\n", argv[0]);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
host = argv[1];
|
||||||
|
port = atoi(argv[2]);
|
||||||
|
|
||||||
|
client_sock = open_client_sock(host, port);
|
||||||
|
if(client_sock==-1) {
|
||||||
|
fputs("Error to connect the Server\n",stdout);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
while (fgets(buf, MAXLINE, stdin) != NULL) {
|
||||||
|
ftp_file_t file;
|
||||||
|
FILE *fp;
|
||||||
|
long fileSize;
|
||||||
|
|
||||||
|
char filePath[MAXLINE] = "./"; // 假设当前目录下有文件
|
||||||
|
|
||||||
|
char *token = strtok(buf, " \t\n"); // 提取FTP命令
|
||||||
|
if (strcmp(token, "get") == 0 || strcmp(token, "put") == 0) {
|
||||||
|
strncpy(file.cmd, token, MAXLINE - 1);
|
||||||
|
file.cmd[MAXLINE - 1] = '\0';
|
||||||
|
} else {
|
||||||
|
printf("Unsupported command: %s\n", token);
|
||||||
|
continue; // 如果不是get或put命令,跳过处理
|
||||||
|
}
|
||||||
|
|
||||||
|
token = strtok(NULL, " \t\n"); // 提取文件名参数
|
||||||
|
if (token != NULL) {
|
||||||
|
strncpy(file.filename, token, MAXLINE - 1);
|
||||||
|
file.filename[MAXLINE - 1] = '\0';
|
||||||
|
} else {
|
||||||
|
printf("Filename is required for command: %s\n", file.cmd);
|
||||||
|
continue; // 如果没有提供文件名参数,跳过处理
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if (strcmp(file.cmd,"put")==0)
|
||||||
|
{
|
||||||
|
strcat(filePath, file.filename); // 构建完整文件路径
|
||||||
|
fp = fopen(filePath, "r");
|
||||||
|
if (fp == NULL) {
|
||||||
|
perror("Error opening file");
|
||||||
|
continue;
|
||||||
|
} else {
|
||||||
|
fseek(fp, 0, SEEK_END);
|
||||||
|
fileSize = ftell(fp);
|
||||||
|
fclose(fp);
|
||||||
|
snprintf(file.fileSize, MAXLINE, "%ld", fileSize); // 将文件大小转换为字符串并存储
|
||||||
|
}
|
||||||
|
|
||||||
|
send(client_sock, &file, sizeof(ftp_file_t), 0);
|
||||||
|
fp = fopen(filePath, "r");
|
||||||
|
if (fp == NULL) {
|
||||||
|
perror("Error opening file for reading");
|
||||||
|
} else {
|
||||||
|
char *fileContent = malloc(fileSize);
|
||||||
|
fread(fileContent, 1, fileSize, fp); // 从文件中读取内容到缓冲区
|
||||||
|
send(client_sock, fileContent, fileSize, 0); // 发送文件内容
|
||||||
|
free(fileContent);
|
||||||
|
recv(client_sock, buf, MAXLINE, 0);
|
||||||
|
fputs(buf, stdout);
|
||||||
|
fclose(fp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (strcmp(file.cmd,"get")==0)
|
||||||
|
{
|
||||||
|
send(client_sock, &file, sizeof(ftp_file_t), 0);
|
||||||
|
recv(client_sock, &file, sizeof(ftp_file_t), 0); // 接收文件信息
|
||||||
|
int fileSize = atoi(file.fileSize);
|
||||||
|
if (fileSize > 0) {
|
||||||
|
char *fileContent = malloc(fileSize); // 根据文件大小分配内存
|
||||||
|
recv(client_sock, fileContent, fileSize, 0); // 接收文件内容
|
||||||
|
FILE *fp = fopen(file.filename, "w");
|
||||||
|
if (fp != NULL) {
|
||||||
|
fwrite(fileContent, 1, fileSize, fp); // 将接收到的内容写入文件
|
||||||
|
fclose(fp);
|
||||||
|
} else {
|
||||||
|
perror("Error creating file");
|
||||||
|
}
|
||||||
|
free(fileContent); // 释放内存
|
||||||
|
}
|
||||||
|
recv(client_sock, buf, MAXLINE, 0);
|
||||||
|
fputs(buf, stdout);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
close(client_sock);
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
0
server-exp/ftpc.c:Zone.Identifier
Normal file
0
server-exp/ftpc.c:Zone.Identifier
Normal file
BIN
server-exp/ftps
Executable file
BIN
server-exp/ftps
Executable file
Binary file not shown.
101
server-exp/ftps.c
Normal file
101
server-exp/ftps.c
Normal file
@@ -0,0 +1,101 @@
|
|||||||
|
#include "common.h"
|
||||||
|
|
||||||
|
typedef struct ftp_file
|
||||||
|
{
|
||||||
|
char cmd[MAXLINE]; // FTP命令
|
||||||
|
char filename[MAXLINE]; // 文件名参数
|
||||||
|
char fileSize[MAXLINE]; // 文件大小参数
|
||||||
|
} ftp_file_t;
|
||||||
|
|
||||||
|
void toggle(int conn_sock,int hit)
|
||||||
|
{
|
||||||
|
size_t n; int i,no=0;
|
||||||
|
char buf[MAXBUF];
|
||||||
|
ftp_file_t file;
|
||||||
|
char filePath[MAXLINE] = "./"; // 假设当前目录下有文件
|
||||||
|
|
||||||
|
printf("第%d个客户通信开始\n",hit);
|
||||||
|
while((n =recv(conn_sock, &file, sizeof(ftp_file_t),0))> 0) {
|
||||||
|
printf("toggle服务器收到第%d个客户第%d个消息,长度为%d字节\n", hit,++no,(int)n);
|
||||||
|
if (strcmp(file.cmd,"put")==0)
|
||||||
|
{
|
||||||
|
int fileSize = atoi(file.fileSize);
|
||||||
|
char *fileContent = malloc(fileSize);
|
||||||
|
recv(conn_sock, fileContent, fileSize, 0); // 接收文件内容
|
||||||
|
FILE *fp = fopen(file.filename, "w");
|
||||||
|
if (fp == NULL) {
|
||||||
|
perror("Error opening file for writing");
|
||||||
|
} else {
|
||||||
|
fwrite(fileContent, 1, fileSize, fp); // 将接收到的内容写入文件
|
||||||
|
fclose(fp);
|
||||||
|
}
|
||||||
|
free(fileContent);
|
||||||
|
strcpy(buf, "File received successfully\n");
|
||||||
|
send (conn_sock, buf, strlen(buf), 0);
|
||||||
|
}
|
||||||
|
else if (strcmp(file.cmd,"get")==0)
|
||||||
|
{
|
||||||
|
strcat(filePath, file.filename); // 构建完整文件路径
|
||||||
|
FILE *fp = fopen(filePath, "r");
|
||||||
|
if (fp == NULL) {
|
||||||
|
perror("Error opening file for reading");
|
||||||
|
strcpy(file.fileSize, "0");
|
||||||
|
send(conn_sock, &file, sizeof(ftp_file_t), 0); // 发送错误信息
|
||||||
|
} else {
|
||||||
|
fseek(fp, 0, SEEK_END);
|
||||||
|
long fileSize = ftell(fp);
|
||||||
|
fclose(fp);
|
||||||
|
snprintf(file.fileSize, MAXLINE, "%ld", fileSize); // 将文件大小转换为字符串并存储
|
||||||
|
send(conn_sock, &file, sizeof(ftp_file_t), 0); // 发送文件信息
|
||||||
|
fp = fopen(filePath, "r");
|
||||||
|
if (fp != NULL) {
|
||||||
|
char *fileContent = malloc(fileSize);
|
||||||
|
fread(fileContent, 1, fileSize, fp); // 从文件中读取内容到缓冲区
|
||||||
|
fclose(fp);
|
||||||
|
send(conn_sock, fileContent, fileSize, 0); // 发送文件内容
|
||||||
|
free(fileContent);
|
||||||
|
strcpy(buf, "File sent successfully\n");
|
||||||
|
send (conn_sock, buf, strlen(buf), 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
printf("第%d个客户通信结束\n",hit);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
int listen_sock, conn_sock, port, clientlen;
|
||||||
|
struct sockaddr_in clientaddr;
|
||||||
|
struct hostent *hp;
|
||||||
|
char *haddrp;
|
||||||
|
int hit;
|
||||||
|
|
||||||
|
if (argc != 2) {
|
||||||
|
fprintf(stderr, "usage: %s <port>\n", argv[0]);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
port = atoi(argv[1]);
|
||||||
|
|
||||||
|
listen_sock = open_listen_sock(port);
|
||||||
|
if( listen_sock==-1) {
|
||||||
|
printf("端口号%d繁忙\n",port);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (hit=1; ; hit++) {
|
||||||
|
clientlen = sizeof(clientaddr);
|
||||||
|
conn_sock = accept(listen_sock, (SA *)&clientaddr, &clientlen);
|
||||||
|
|
||||||
|
/* determine the domain name and IP address of the client */
|
||||||
|
hp = gethostbyaddr((const char *)&clientaddr.sin_addr.s_addr,
|
||||||
|
sizeof(clientaddr.sin_addr.s_addr), AF_INET);
|
||||||
|
haddrp = inet_ntoa(clientaddr.sin_addr);
|
||||||
|
printf("server connected to %s (%s)\n", hp->h_name, haddrp);
|
||||||
|
|
||||||
|
toggle(conn_sock,hit);
|
||||||
|
close(conn_sock);
|
||||||
|
}
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
0
server-exp/ftps.c:Zone.Identifier
Normal file
0
server-exp/ftps.c:Zone.Identifier
Normal file
BIN
server-exp/http_load-09Mar2016.tar.gz
Normal file
BIN
server-exp/http_load-09Mar2016.tar.gz
Normal file
Binary file not shown.
13
server-exp/index.html
Normal file
13
server-exp/index.html
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<link rel="shortcut icon" href="favicon.ico" type="image/x-icon"/>
|
||||||
|
<title>the example web</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<H1>webserver test page</H1>
|
||||||
|
<p>
|
||||||
|
Not pretty but should prove that webserver works:-)
|
||||||
|
<p>
|
||||||
|
<IMG SRC="example.jpg">
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
214
server-exp/perf.txt
Normal file
214
server-exp/perf.txt
Normal file
@@ -0,0 +1,214 @@
|
|||||||
|
Flat profile:
|
||||||
|
|
||||||
|
Each sample counts as 0.01 seconds.
|
||||||
|
% cumulative self self total
|
||||||
|
time seconds seconds calls ns/call ns/call name
|
||||||
|
28.57 0.10 0.10 1461740 68.41 116.30 rio_readlineb
|
||||||
|
25.71 0.19 0.09 365435 246.28 930.40 process_trans
|
||||||
|
20.00 0.26 0.07 29966110 2.34 2.34 rio_read
|
||||||
|
5.71 0.28 0.02 974534 20.52 20.52 rio_writen
|
||||||
|
5.71 0.30 0.02 243603 82.10 123.15 feed_static
|
||||||
|
5.71 0.32 0.02 121832 164.16 246.25 error_request
|
||||||
|
2.86 0.33 0.01 365435 27.36 376.26 read_requesthdrs
|
||||||
|
2.86 0.34 0.01 121832 82.08 82.08 parse_dynamic_uri
|
||||||
|
2.86 0.35 0.01 main
|
||||||
|
0.00 0.35 0.00 365435 0.00 0.00 is_static
|
||||||
|
0.00 0.35 0.00 365435 0.00 0.00 rio_readinitb
|
||||||
|
0.00 0.35 0.00 243603 0.00 0.00 get_filetype
|
||||||
|
0.00 0.35 0.00 243603 0.00 0.00 parse_static_uri
|
||||||
|
0.00 0.35 0.00 1 0.00 0.00 open_listen_sock
|
||||||
|
|
||||||
|
% the percentage of the total running time of the
|
||||||
|
time program used by this function.
|
||||||
|
|
||||||
|
cumulative a running sum of the number of seconds accounted
|
||||||
|
seconds for by this function and those listed above it.
|
||||||
|
|
||||||
|
self the number of seconds accounted for by this
|
||||||
|
seconds function alone. This is the major sort for this
|
||||||
|
listing.
|
||||||
|
|
||||||
|
calls the number of times this function was invoked, if
|
||||||
|
this function is profiled, else blank.
|
||||||
|
|
||||||
|
self the average number of milliseconds spent in this
|
||||||
|
ms/call function per call, if this function is profiled,
|
||||||
|
else blank.
|
||||||
|
|
||||||
|
total the average number of milliseconds spent in this
|
||||||
|
ms/call function and its descendents per call, if this
|
||||||
|
function is profiled, else blank.
|
||||||
|
|
||||||
|
name the name of the function. This is the minor sort
|
||||||
|
for this listing. The index shows the location of
|
||||||
|
the function in the gprof listing. If the index is
|
||||||
|
in parenthesis it shows where it would appear in
|
||||||
|
the gprof listing if it were to be printed.
|
||||||
|
|
||||||
|
Copyright (C) 2012-2026 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
Copying and distribution of this file, with or without modification,
|
||||||
|
are permitted in any medium without royalty provided the copyright
|
||||||
|
notice and this notice are preserved.
|
||||||
|
|
||||||
|
Call graph (explanation follows)
|
||||||
|
|
||||||
|
|
||||||
|
granularity: each sample hit covers 4 byte(s) for 2.86% of 0.35 seconds
|
||||||
|
|
||||||
|
index % time self children called name
|
||||||
|
<spontaneous>
|
||||||
|
[1] 100.0 0.01 0.34 main [1]
|
||||||
|
0.09 0.25 365435/365435 process_trans [2]
|
||||||
|
0.00 0.00 1/1 open_listen_sock [14]
|
||||||
|
-----------------------------------------------
|
||||||
|
0.09 0.25 365435/365435 main [1]
|
||||||
|
[2] 97.1 0.09 0.25 365435 process_trans [2]
|
||||||
|
0.01 0.13 365435/365435 read_requesthdrs [4]
|
||||||
|
0.03 0.02 365435/1461740 rio_readlineb [3]
|
||||||
|
0.02 0.01 121832/121832 error_request [6]
|
||||||
|
0.02 0.01 243603/243603 feed_static [7]
|
||||||
|
0.01 0.00 121832/121832 parse_dynamic_uri [9]
|
||||||
|
0.00 0.00 365435/365435 rio_readinitb [11]
|
||||||
|
0.00 0.00 365435/365435 is_static [10]
|
||||||
|
0.00 0.00 243603/243603 parse_static_uri [13]
|
||||||
|
-----------------------------------------------
|
||||||
|
0.03 0.02 365435/1461740 process_trans [2]
|
||||||
|
0.07 0.05 1096305/1461740 read_requesthdrs [4]
|
||||||
|
[3] 48.6 0.10 0.07 1461740 rio_readlineb [3]
|
||||||
|
0.07 0.00 29966110/29966110 rio_read [5]
|
||||||
|
-----------------------------------------------
|
||||||
|
0.01 0.13 365435/365435 process_trans [2]
|
||||||
|
[4] 39.3 0.01 0.13 365435 read_requesthdrs [4]
|
||||||
|
0.07 0.05 1096305/1461740 rio_readlineb [3]
|
||||||
|
-----------------------------------------------
|
||||||
|
0.07 0.00 29966110/29966110 rio_readlineb [3]
|
||||||
|
[5] 20.0 0.07 0.00 29966110 rio_read [5]
|
||||||
|
-----------------------------------------------
|
||||||
|
0.02 0.01 121832/121832 process_trans [2]
|
||||||
|
[6] 8.6 0.02 0.01 121832 error_request [6]
|
||||||
|
0.01 0.00 487328/974534 rio_writen [8]
|
||||||
|
-----------------------------------------------
|
||||||
|
0.02 0.01 243603/243603 process_trans [2]
|
||||||
|
[7] 8.6 0.02 0.01 243603 feed_static [7]
|
||||||
|
0.01 0.00 487206/974534 rio_writen [8]
|
||||||
|
0.00 0.00 243603/243603 get_filetype [12]
|
||||||
|
-----------------------------------------------
|
||||||
|
0.01 0.00 487206/974534 feed_static [7]
|
||||||
|
0.01 0.00 487328/974534 error_request [6]
|
||||||
|
[8] 5.7 0.02 0.00 974534 rio_writen [8]
|
||||||
|
-----------------------------------------------
|
||||||
|
0.01 0.00 121832/121832 process_trans [2]
|
||||||
|
[9] 2.9 0.01 0.00 121832 parse_dynamic_uri [9]
|
||||||
|
-----------------------------------------------
|
||||||
|
0.00 0.00 365435/365435 process_trans [2]
|
||||||
|
[10] 0.0 0.00 0.00 365435 is_static [10]
|
||||||
|
-----------------------------------------------
|
||||||
|
0.00 0.00 365435/365435 process_trans [2]
|
||||||
|
[11] 0.0 0.00 0.00 365435 rio_readinitb [11]
|
||||||
|
-----------------------------------------------
|
||||||
|
0.00 0.00 243603/243603 feed_static [7]
|
||||||
|
[12] 0.0 0.00 0.00 243603 get_filetype [12]
|
||||||
|
-----------------------------------------------
|
||||||
|
0.00 0.00 243603/243603 process_trans [2]
|
||||||
|
[13] 0.0 0.00 0.00 243603 parse_static_uri [13]
|
||||||
|
-----------------------------------------------
|
||||||
|
0.00 0.00 1/1 main [1]
|
||||||
|
[14] 0.0 0.00 0.00 1 open_listen_sock [14]
|
||||||
|
-----------------------------------------------
|
||||||
|
|
||||||
|
This table describes the call tree of the program, and was sorted by
|
||||||
|
the total amount of time spent in each function and its children.
|
||||||
|
|
||||||
|
Each entry in this table consists of several lines. The line with the
|
||||||
|
index number at the left hand margin lists the current function.
|
||||||
|
The lines above it list the functions that called this function,
|
||||||
|
and the lines below it list the functions this one called.
|
||||||
|
This line lists:
|
||||||
|
index A unique number given to each element of the table.
|
||||||
|
Index numbers are sorted numerically.
|
||||||
|
The index number is printed next to every function name so
|
||||||
|
it is easier to look up where the function is in the table.
|
||||||
|
|
||||||
|
% time This is the percentage of the `total' time that was spent
|
||||||
|
in this function and its children. Note that due to
|
||||||
|
different viewpoints, functions excluded by options, etc,
|
||||||
|
these numbers will NOT add up to 100%.
|
||||||
|
|
||||||
|
self This is the total amount of time spent in this function.
|
||||||
|
|
||||||
|
children This is the total amount of time propagated into this
|
||||||
|
function by its children.
|
||||||
|
|
||||||
|
called This is the number of times the function was called.
|
||||||
|
If the function called itself recursively, the number
|
||||||
|
only includes non-recursive calls, and is followed by
|
||||||
|
a `+' and the number of recursive calls.
|
||||||
|
|
||||||
|
name The name of the current function. The index number is
|
||||||
|
printed after it. If the function is a member of a
|
||||||
|
cycle, the cycle number is printed between the
|
||||||
|
function's name and the index number.
|
||||||
|
|
||||||
|
|
||||||
|
For the function's parents, the fields have the following meanings:
|
||||||
|
|
||||||
|
self This is the amount of time that was propagated directly
|
||||||
|
from the function into this parent.
|
||||||
|
|
||||||
|
children This is the amount of time that was propagated from
|
||||||
|
the function's children into this parent.
|
||||||
|
|
||||||
|
called This is the number of times this parent called the
|
||||||
|
function `/' the total number of times the function
|
||||||
|
was called. Recursive calls to the function are not
|
||||||
|
included in the number after the `/'.
|
||||||
|
|
||||||
|
name This is the name of the parent. The parent's index
|
||||||
|
number is printed after it. If the parent is a
|
||||||
|
member of a cycle, the cycle number is printed between
|
||||||
|
the name and the index number.
|
||||||
|
|
||||||
|
If the parents of the function cannot be determined, the word
|
||||||
|
`<spontaneous>' is printed in the `name' field, and all the other
|
||||||
|
fields are blank.
|
||||||
|
|
||||||
|
For the function's children, the fields have the following meanings:
|
||||||
|
|
||||||
|
self This is the amount of time that was propagated directly
|
||||||
|
from the child into the function.
|
||||||
|
|
||||||
|
children This is the amount of time that was propagated from the
|
||||||
|
child's children to the function.
|
||||||
|
|
||||||
|
called This is the number of times the function called
|
||||||
|
this child `/' the total number of times the child
|
||||||
|
was called. Recursive calls by the child are not
|
||||||
|
listed in the number after the `/'.
|
||||||
|
|
||||||
|
name This is the name of the child. The child's index
|
||||||
|
number is printed after it. If the child is a
|
||||||
|
member of a cycle, the cycle number is printed
|
||||||
|
between the name and the index number.
|
||||||
|
|
||||||
|
If there are any cycles (circles) in the call graph, there is an
|
||||||
|
entry for the cycle-as-a-whole. This entry shows who called the
|
||||||
|
cycle (as parents) and the members of the cycle (as children.)
|
||||||
|
The `+' recursive calls entry shows the number of function calls that
|
||||||
|
were internal to the cycle, and the calls entry for each member shows,
|
||||||
|
for that member, how many times it was called from other members of
|
||||||
|
the cycle.
|
||||||
|
|
||||||
|
Copyright (C) 2012-2026 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
Copying and distribution of this file, with or without modification,
|
||||||
|
are permitted in any medium without royalty provided the copyright
|
||||||
|
notice and this notice are preserved.
|
||||||
|
|
||||||
|
Index by function name
|
||||||
|
|
||||||
|
[6] error_request [14] open_listen_sock [5] rio_read (common.c)
|
||||||
|
[7] feed_static [9] parse_dynamic_uri [11] rio_readinitb
|
||||||
|
[12] get_filetype [13] parse_static_uri [3] rio_readlineb
|
||||||
|
[10] is_static [2] process_trans [8] rio_writen
|
||||||
|
[1] main [4] read_requesthdrs
|
||||||
8
server-exp/test.html
Normal file
8
server-exp/test.html
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>a simple page for testing tiny</title>
|
||||||
|
<head>
|
||||||
|
<body>
|
||||||
|
Hello World
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
1
server-exp/testfile.txt
Normal file
1
server-exp/testfile.txt
Normal file
@@ -0,0 +1 @@
|
|||||||
|
hello ftp test
|
||||||
BIN
server-exp/togglec
Executable file
BIN
server-exp/togglec
Executable file
Binary file not shown.
29
server-exp/togglec.c
Normal file
29
server-exp/togglec.c
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
#include "common.h"
|
||||||
|
|
||||||
|
int main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
int client_sock, port;
|
||||||
|
char *host, buf[MAXLINE];
|
||||||
|
rio_t rio;
|
||||||
|
|
||||||
|
if (argc != 3) {
|
||||||
|
fprintf(stderr, "usage: %s <host><port>\n", argv[0]);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
host = argv[1];
|
||||||
|
port = atoi(argv[2]);
|
||||||
|
|
||||||
|
client_sock = open_client_sock(host, port);
|
||||||
|
if(client_sock==-1) {
|
||||||
|
fputs("Error to connect the Server\n",stdout);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
while (fgets(buf, MAXLINE, stdin) != NULL) {
|
||||||
|
send(client_sock, buf, strlen(buf),0);
|
||||||
|
recv(client_sock, buf, MAXLINE,0);
|
||||||
|
fputs(buf, stdout);
|
||||||
|
}
|
||||||
|
close(client_sock);
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
BIN
server-exp/togglesi
Executable file
BIN
server-exp/togglesi
Executable file
Binary file not shown.
57
server-exp/togglesi.c
Normal file
57
server-exp/togglesi.c
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
#include "common.h"
|
||||||
|
|
||||||
|
void toggle(int conn_sock,int hit)
|
||||||
|
{
|
||||||
|
size_t n; int i,no=0;
|
||||||
|
char buf[MAXLINE];
|
||||||
|
|
||||||
|
printf("第%d个客户通信开始\n",hit);
|
||||||
|
while((n =recv(conn_sock, buf, MAXLINE,0))> 0) {
|
||||||
|
printf("toggle服务器收到第%d个客户第%d个消息,长度为%d字节\n", hit,++no,(int)n);
|
||||||
|
|
||||||
|
for(i=0; i<n; i++)
|
||||||
|
if(isupper(buf[i]))
|
||||||
|
buf[i]=tolower(buf[i]);
|
||||||
|
else if(islower(buf[i]))
|
||||||
|
buf[i]=toupper(buf[i]);
|
||||||
|
|
||||||
|
send (conn_sock, buf, n, 0);
|
||||||
|
}
|
||||||
|
printf("第%d个客户通信结束\n",hit);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
int listen_sock, conn_sock, port, clientlen;
|
||||||
|
struct sockaddr_in clientaddr;
|
||||||
|
struct hostent *hp;
|
||||||
|
char *haddrp;
|
||||||
|
int hit;
|
||||||
|
|
||||||
|
if (argc != 2) {
|
||||||
|
fprintf(stderr, "usage: %s <port>\n", argv[0]);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
port = atoi(argv[1]);
|
||||||
|
|
||||||
|
listen_sock = open_listen_sock(port);
|
||||||
|
if( listen_sock==-1) {
|
||||||
|
printf("端口号%d繁忙\n",port);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (hit=1; ; hit++) {
|
||||||
|
clientlen = sizeof(clientaddr);
|
||||||
|
conn_sock = accept(listen_sock, (SA *)&clientaddr, &clientlen);
|
||||||
|
|
||||||
|
/* determine the domain name and IP address of the client */
|
||||||
|
hp = gethostbyaddr((const char *)&clientaddr.sin_addr.s_addr,
|
||||||
|
sizeof(clientaddr.sin_addr.s_addr), AF_INET);
|
||||||
|
haddrp = inet_ntoa(clientaddr.sin_addr);
|
||||||
|
printf("server connected to %s (%s)\n", hp->h_name, haddrp);
|
||||||
|
|
||||||
|
toggle(conn_sock,hit);
|
||||||
|
close(conn_sock);
|
||||||
|
}
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
3
server-exp/urls
Normal file
3
server-exp/urls
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
http://127.0.0.1:8088/index.html
|
||||||
|
http://127.0.0.1:8088/test.html
|
||||||
|
http://127.0.0.1:8088/cgi-bin/add?2025&523808
|
||||||
BIN
server-exp/webclient
Executable file
BIN
server-exp/webclient
Executable file
Binary file not shown.
55
server-exp/webclient.c
Normal file
55
server-exp/webclient.c
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
#include <arpa/inet.h> // 提供IP地址转换函数
|
||||||
|
#include <netinet/in.h> // 提供套接字地址结构定义
|
||||||
|
#include <stdio.h> // 标准输入输出
|
||||||
|
#include <stdlib.h> // 标准库函数,如exit()
|
||||||
|
#include <string.h> // 字符串操作函数
|
||||||
|
#include <sys/socket.h> // 套接字相关函数
|
||||||
|
#include <sys/types.h> // 数据类型定义
|
||||||
|
#include <unistd.h> // POSIX API,如read()和write()
|
||||||
|
|
||||||
|
//#define PORT 8181 /* 目标服务器的端口号 */
|
||||||
|
//#define IP_ADDRESS "192.168.0.8" /* 目标服务器的IP地址 */
|
||||||
|
#define BUFSIZE 8196 /* 缓冲区大小 */
|
||||||
|
|
||||||
|
char *command = "GET /index.html HTTP/1.0 \r\n\r\n"; /* HTTP GET 请求命令 */
|
||||||
|
|
||||||
|
// 错误处理函数,打印错误信息并退出程序
|
||||||
|
void pexit(char *msg) {
|
||||||
|
perror(msg); // 打印错误信息
|
||||||
|
exit(1); // 退出程序
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char *argv[]) {//客户端启动命令为"./webclient 127.0.0.1 8088",argv[1]是IP地址,argv[2]是端口号8088
|
||||||
|
int i, sockfd; // sockfd是套接字文件描述符
|
||||||
|
char buffer[BUFSIZE]; // 用于存储从服务器接收的数据
|
||||||
|
struct sockaddr_in serv_addr; // 定义服务器地址结构
|
||||||
|
|
||||||
|
// 打印尝试连接服务器的信息
|
||||||
|
printf("客户端尝试连接到 %s 和端口 %s\n", argv[1], argv[2]);
|
||||||
|
|
||||||
|
// 创建套接字,使用IPv4和TCP协议
|
||||||
|
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) pexit("socket() 创建失败");
|
||||||
|
|
||||||
|
// 配置服务器地址
|
||||||
|
serv_addr.sin_family = AF_INET; // 地址族为IPv4
|
||||||
|
serv_addr.sin_addr.s_addr = inet_addr(argv[1]); // 设置服务器IP地址,如"127.0.0.1"
|
||||||
|
serv_addr.sin_port = htons(atoi(argv[2])); // 设置服务器端口号,如"8088"
|
||||||
|
|
||||||
|
// 尝试连接到服务器
|
||||||
|
if (connect(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0)
|
||||||
|
pexit("connect() 连接失败");
|
||||||
|
|
||||||
|
// 发送HTTP GET请求到服务器
|
||||||
|
printf("发送字节数=%ld %s\n", strlen(command), command);
|
||||||
|
if (write(sockfd, command, strlen(command)) < 0) pexit("write() 发送请求失败");
|
||||||
|
|
||||||
|
// 循环读取服务器返回的数据,并输出到标准输出
|
||||||
|
while ((i = read(sockfd, buffer, BUFSIZE)) > 0) {
|
||||||
|
if (write(1, buffer, i) < 0) // 1表示标准输出
|
||||||
|
pexit("write() 输出到标准输出失败");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 关闭套接字,释放资源
|
||||||
|
close(sockfd);
|
||||||
|
return 0; // 程序正常退出
|
||||||
|
}
|
||||||
BIN
server-exp/weblet
Executable file
BIN
server-exp/weblet
Executable file
Binary file not shown.
278
server-exp/weblet.c
Normal file
278
server-exp/weblet.c
Normal file
@@ -0,0 +1,278 @@
|
|||||||
|
#include "common.h"
|
||||||
|
|
||||||
|
void process_trans(int fd,int hit);
|
||||||
|
void read_requesthdrs(rio_t *rp,int hit,int nrh);
|
||||||
|
int is_static(char *uri);
|
||||||
|
void parse_static_uri(char *uri, char *filename);
|
||||||
|
void parse_dynamic_uri(char *uri, char *filename, char *cgiargs);
|
||||||
|
void feed_static(int fd, char *filename, int filesize);
|
||||||
|
void get_filetype(char *filename, char *filetype);
|
||||||
|
void feed_dynamic(int fd, char *filename, char *cgiargs);
|
||||||
|
void error_request(int fd, char *cause, char *errnum,
|
||||||
|
char *shortmsg, char *description);
|
||||||
|
|
||||||
|
/* 支持的文件扩展名及其对应的MIME类型 */
|
||||||
|
struct {
|
||||||
|
char *ext; // 文件扩展名
|
||||||
|
char *filetype; // MIME类型
|
||||||
|
} extensions[] = {
|
||||||
|
{".gif", "image/gif"},
|
||||||
|
{".jpg", "image/jpg"},
|
||||||
|
{".jpeg", "image/jpeg"},
|
||||||
|
{".png", "image/png"},
|
||||||
|
{".ico", "image/ico"},
|
||||||
|
{".zip", "image/zip"},
|
||||||
|
{".gz", "image/gz"},
|
||||||
|
{".tar", "image/tar"},
|
||||||
|
{".htm", "text/html"},
|
||||||
|
{".html", "text/html"},
|
||||||
|
{0, 0} // 结束标志
|
||||||
|
};
|
||||||
|
|
||||||
|
/* 调试模式宏定义 */
|
||||||
|
#ifdef DEBUG
|
||||||
|
#define printf2(format, var) printf(format,var)
|
||||||
|
#define printf3(format,var1,var2) printf(format,var1,var2)
|
||||||
|
#else
|
||||||
|
#define printf2(format, var)
|
||||||
|
#define printf3(format,var1,var2)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* 全局变量说明 */
|
||||||
|
|
||||||
|
|
||||||
|
/* Ctrl+C信号处理函数 */
|
||||||
|
void ctrlc_handler(int sig)
|
||||||
|
{
|
||||||
|
printf("您按下了Ctrl+C终止了Web服务器\n");
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 主函数:监听端口并处理客户端连接 */
|
||||||
|
|
||||||
|
int main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
int listen_sock, conn_sock, port;
|
||||||
|
int hit; // 请求计数器
|
||||||
|
socklen_t clientlen;
|
||||||
|
struct sockaddr_in clientaddr;
|
||||||
|
|
||||||
|
/* 检查命令行参数 */
|
||||||
|
if (argc != 2) {
|
||||||
|
fprintf(stderr, "用法: %s <端口号>\n", argv[0]);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 设置Ctrl+C信号处理 */
|
||||||
|
if(signal(SIGINT,ctrlc_handler)==SIG_ERR)
|
||||||
|
(void)printf("错误: 无法设置SIGINT信号处理\n");
|
||||||
|
|
||||||
|
port = atoi(argv[1]);
|
||||||
|
|
||||||
|
listen_sock = open_listen_sock(port);
|
||||||
|
for (hit=1; ; hit++) { //hit为第几次请求,或第几次http事务
|
||||||
|
clientlen = sizeof(clientaddr);
|
||||||
|
conn_sock = accept(listen_sock, (SA *)&clientaddr, &clientlen);
|
||||||
|
process_trans(conn_sock,hit); // 处理HTTP事务
|
||||||
|
close(conn_sock);
|
||||||
|
}
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 处理HTTP事务的核心函数 */
|
||||||
|
void process_trans(int fd,int hit)
|
||||||
|
{
|
||||||
|
int static_flag; // 是否为静态资源标志
|
||||||
|
struct stat sbuf; // 文件状态信息
|
||||||
|
char buf[MAXLINE], method[MAXLINE]="", uri[MAXLINE]="", version[MAXLINE]="http/1.1";
|
||||||
|
char filename[MAXLINE], cgiargs[MAXLINE];
|
||||||
|
|
||||||
|
rio_t rio;
|
||||||
|
int rhn=0; // 请求头计数器
|
||||||
|
|
||||||
|
printf2("第%d次请求开始\n",hit);
|
||||||
|
|
||||||
|
/* 读取请求行和请求头 */
|
||||||
|
rio_readinitb(&rio, fd);
|
||||||
|
rio_readlineb(&rio, buf, MAXLINE);
|
||||||
|
printf3("请求头%d:%s", ++rhn, buf);
|
||||||
|
|
||||||
|
//判断第一个请求行是否正好有三个单词构成,如GET / http/1.1
|
||||||
|
/*int wn=0; char *p=buf;
|
||||||
|
while(*p==' ' || *p=='\t') p++;
|
||||||
|
while(*p) {
|
||||||
|
if((*p==' '||*p=='\t') && *(p+1)!=' ') wn++;
|
||||||
|
p++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (wn==2) */
|
||||||
|
sscanf(buf, "%s %s %s", method, uri, version);
|
||||||
|
|
||||||
|
if (strcasecmp(method, "GET")) { // 仅支持GET方法
|
||||||
|
error_request(fd, method, "501", "未实现",
|
||||||
|
"本服务器不支持该请求方法");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
read_requesthdrs(&rio,hit,rhn); // 读取剩余请求头
|
||||||
|
|
||||||
|
static_flag = is_static(uri); // 判断资源类型
|
||||||
|
if(static_flag)
|
||||||
|
parse_static_uri(uri, filename); // 解析静态资源路径
|
||||||
|
else
|
||||||
|
parse_dynamic_uri(uri, filename, cgiargs); // 解析动态资源路径和参数
|
||||||
|
|
||||||
|
/* 检查文件是否存在及权限 */
|
||||||
|
if (stat(filename, &sbuf) < 0) {
|
||||||
|
error_request(fd, filename, "404", "未找到",
|
||||||
|
"服务器无法找到该文件");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 根据资源类型发送响应 */
|
||||||
|
if (static_flag) { // 静态资源处理
|
||||||
|
if (!(S_ISREG(sbuf.st_mode)) || !(S_IRUSR & sbuf.st_mode)) {
|
||||||
|
error_request(fd, filename, "403", "禁止访问",
|
||||||
|
"服务器无权读取该文件");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
feed_static(fd, filename, sbuf.st_size); // 发送静态文件内容
|
||||||
|
}
|
||||||
|
else { // 动态资源处理
|
||||||
|
if (!(S_ISREG(sbuf.st_mode)) || !(S_IXUSR & sbuf.st_mode)) {
|
||||||
|
error_request(fd, filename, "403", "禁止访问",
|
||||||
|
"服务器无法执行该CGI程序");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
feed_dynamic(fd, filename, cgiargs); // 执行CGI程序并发送输出
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 判断URI是否对应静态资源 */
|
||||||
|
int is_static(char *uri)
|
||||||
|
{
|
||||||
|
return strstr(uri, "cgi-bin") == NULL; // 不含cgi-bin则为静态资源
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 构造HTTP错误响应 */
|
||||||
|
void error_request(int fd, char *cause, char *errnum,
|
||||||
|
char *shortmsg, char *description)
|
||||||
|
{
|
||||||
|
char buf[MAXLINE], body[MAXBUF];
|
||||||
|
|
||||||
|
/* 构建错误页面内容 */
|
||||||
|
sprintf(body, "<html><title>错误请求</title>");
|
||||||
|
sprintf(body, "%s<body bgcolor=\"#ffffff\">\r\n", body);
|
||||||
|
sprintf(body, "%s<h1>%s %s</h1>\r\n", body, errnum, shortmsg);
|
||||||
|
sprintf(body, "%s<p>%s: %s</p>\r\n", body, description, cause);
|
||||||
|
sprintf(body, "%s<hr><em>weblet Web服务器</em>\r\n", body);
|
||||||
|
|
||||||
|
/* 发送HTTP响应头 */
|
||||||
|
sprintf(buf, "HTTP/1.0 %s %s\r\n", errnum, shortmsg);
|
||||||
|
rio_writen(fd, buf, strlen(buf));
|
||||||
|
sprintf(buf, "Content-type: text/html\r\n");
|
||||||
|
rio_writen(fd, buf, strlen(buf));
|
||||||
|
sprintf(buf, "Content-length: %d\r\n\r\n", (int)strlen(body));
|
||||||
|
rio_writen(fd, buf, strlen(buf));
|
||||||
|
|
||||||
|
/* 发送错误页面内容 */
|
||||||
|
rio_writen(fd, body, strlen(body));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 读取请求头直到空行 */
|
||||||
|
void read_requesthdrs(rio_t *rp,int hit, int rhn)
|
||||||
|
{
|
||||||
|
char buf[MAXLINE];
|
||||||
|
rio_readlineb(rp, buf, MAXLINE);
|
||||||
|
while(strcmp(buf, "\r\n")) {
|
||||||
|
printf3("请求头%d:%s", ++rhn, buf);
|
||||||
|
rio_readlineb(rp, buf, MAXLINE);
|
||||||
|
}
|
||||||
|
printf2("第%d次请求结束\n\n",hit);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 解析静态资源URI到文件路径 */
|
||||||
|
void parse_static_uri(char *uri, char *filename)
|
||||||
|
{
|
||||||
|
strcpy(filename, ".");
|
||||||
|
strcat(filename, uri);
|
||||||
|
if (uri[strlen(uri)-1] == '/')
|
||||||
|
strcat(filename, "index.html"); // 默认返回index.html
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 解析动态资源URI到文件路径和参数 */
|
||||||
|
void parse_dynamic_uri(char *uri, char *filename, char *cgiargs)
|
||||||
|
{
|
||||||
|
char *ptr = index(uri, '?');
|
||||||
|
if (ptr) {
|
||||||
|
strcpy(cgiargs, ptr+1); // 提取参数部分
|
||||||
|
*ptr = '\0'; // 截断URI
|
||||||
|
} else {
|
||||||
|
strcpy(cgiargs, "");
|
||||||
|
}
|
||||||
|
strcpy(filename, ".");
|
||||||
|
strcat(filename, uri);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 发送静态文件内容 */
|
||||||
|
void feed_static(int fd, char *filename, int filesize)
|
||||||
|
{
|
||||||
|
int srcfd;
|
||||||
|
char *srcp, filetype[MAXLINE], buf[MAXBUF];
|
||||||
|
|
||||||
|
/* 发送HTTP响应头 */
|
||||||
|
get_filetype(filename, filetype);
|
||||||
|
sprintf(buf, "HTTP/1.0 200 OK\r\n");
|
||||||
|
sprintf(buf, "%sServer: weblet Web Server\r\n", buf);
|
||||||
|
sprintf(buf, "%sContent-length: %d\r\n", buf, filesize);
|
||||||
|
sprintf(buf, "%sContent-type: %s\r\n\r\n", buf, filetype);
|
||||||
|
rio_writen(fd, buf, strlen(buf));
|
||||||
|
|
||||||
|
/* 发送文件内容 */
|
||||||
|
srcfd = open(filename, O_RDONLY, 0);
|
||||||
|
srcp = mmap(0, filesize, PROT_READ, MAP_PRIVATE, srcfd, 0);
|
||||||
|
close(srcfd);
|
||||||
|
rio_writen(fd, srcp, filesize);
|
||||||
|
munmap(srcp, filesize);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 根据文件扩展名获取MIME类型 */
|
||||||
|
void get_filetype(char *filename, char *filetype)
|
||||||
|
{
|
||||||
|
int i, len;
|
||||||
|
strcpy(filetype, "text/html"); // 默认类型
|
||||||
|
for (i = 0; extensions[i].ext != 0; i++) {
|
||||||
|
len = strlen(extensions[i].ext);
|
||||||
|
if (!strcmp(&filename[strlen(filename)-len], extensions[i].ext)) {
|
||||||
|
strcpy(filetype, extensions[i].filetype);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 启动子进程执行CGI程序 */
|
||||||
|
void feed_dynamic(int fd, char *filename, char *cgiargs)
|
||||||
|
{
|
||||||
|
char buf[MAXLINE], *emptylist[] = { NULL };
|
||||||
|
int pfd[2];
|
||||||
|
|
||||||
|
/* 构造HTTP响应头 */
|
||||||
|
sprintf(buf, "HTTP/1.0 200 OK\r\n");
|
||||||
|
rio_writen(fd, buf, strlen(buf));
|
||||||
|
sprintf(buf, "Server: weblet Web Server\r\n");
|
||||||
|
rio_writen(fd, buf, strlen(buf));
|
||||||
|
|
||||||
|
/* 创建管道并启动子进程 */
|
||||||
|
(void)pipe(pfd);
|
||||||
|
if (fork() == 0) { // 子进程
|
||||||
|
close(pfd[1]); // 关闭写端
|
||||||
|
dup2(pfd[0], STDIN_FILENO); // 重定向标准输入
|
||||||
|
dup2(fd, STDOUT_FILENO); // 重定向标准输出到客户端
|
||||||
|
execve(filename, emptylist, environ); // 执行CGI程序
|
||||||
|
}
|
||||||
|
|
||||||
|
close(pfd[0]); // 父进程关闭读端
|
||||||
|
(void)write(pfd[1], cgiargs, strlen(cgiargs)+1); // 传递参数
|
||||||
|
wait(NULL); // 等待子进程结束
|
||||||
|
close(pfd[1]); // 关闭写端
|
||||||
|
}
|
||||||
BIN
server-exp/实验1任务报告web服务器初步实现.docx
Normal file
BIN
server-exp/实验1任务报告web服务器初步实现.docx
Normal file
Binary file not shown.
BIN
server-exp/实验1任务报告web服务器初步实现_填写版.docx
Normal file
BIN
server-exp/实验1任务报告web服务器初步实现_填写版.docx
Normal file
Binary file not shown.
@@ -0,0 +1,4 @@
|
|||||||
|
[ZoneTransfer]
|
||||||
|
ZoneId=3
|
||||||
|
ReferrerUrl=https://lms.dgut.edu.cn/
|
||||||
|
HostUrl=https://uobs.dgut.edu.cn/view/resources/web/17452239027185951.docx?attname=%E5%AE%9E%E9%AA%8C1%E4%BB%BB%E5%8A%A1%E6%8A%A5%E5%91%8A%EF%BC%88web%E6%9C%8D%E5%8A%A1%E5%99%A8%E5%88%9D%E6%AD%A5%E5%AE%9E%E7%8E%B0%EF%BC%89(1).docx
|
||||||
14
server-exp/实验一文件清单.txt
Normal file
14
server-exp/实验一文件清单.txt
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
common.h : 公共头文件、函数声明、常量定义等(由教材wrapper.h简化而来)
|
||||||
|
common.c : RIO函数库和打开网络连接函数源代码(教材中libwrapper.c简化而来)
|
||||||
|
webclient.c: web客户端源代码(《操作系统实验教程》第1章的client.c)
|
||||||
|
webserver.c: web服务器源代码(即教材《Linux编程》第8章的weblet.c)
|
||||||
|
togglec.c : toggle客户端源代码(教材第8章源代码)
|
||||||
|
togglesi.c : 迭代式toggle服务器源代码(教材《Linux编程》第8章源代码)
|
||||||
|
./cgi-bin/add.c: 生成动态网页的cgi程序(教材《Linux编程》第8章)
|
||||||
|
Makefile: 目标和源代码间相互依赖关系文件(参考教材《Linux编程》第3章)
|
||||||
|
index.html: 缺省网页文件
|
||||||
|
example.jpg: 网页文件index.html中内嵌的图片
|
||||||
|
favicon.ico: index.html中内嵌的图标
|
||||||
|
test.html: 第2个测试用网页
|
||||||
|
urls: 记录运行http_load执行时,访问哪些网址
|
||||||
|
gmon.out: grof命令生成的性能数据文件
|
||||||
81151
server-exp2/abc
Normal file
81151
server-exp2/abc
Normal file
File diff suppressed because it is too large
Load Diff
BIN
server-exp2/cgi-bin/add
Normal file
BIN
server-exp2/cgi-bin/add
Normal file
Binary file not shown.
27
server-exp2/cgi-bin/add.c
Normal file
27
server-exp2/cgi-bin/add.c
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#define MAXLINE 8192
|
||||||
|
|
||||||
|
int main(void) {
|
||||||
|
char *buf, *p;
|
||||||
|
char content[MAXLINE];
|
||||||
|
int n1=0, n2=0;
|
||||||
|
|
||||||
|
/* Extract the two arguments from standard input */
|
||||||
|
scanf("%d&%d", &n1, &n2);
|
||||||
|
|
||||||
|
/* Make the response body */
|
||||||
|
sprintf(content, "Welcome to add.com: ");
|
||||||
|
sprintf(content, "%sTHE Internet addition portal.\r\n<p>", content);
|
||||||
|
sprintf(content, "%sThe answer is: %d + %d = %d\r\n<p>",
|
||||||
|
content, n1, n2, n1 + n2);
|
||||||
|
sprintf(content, "%sThanks for visiting!\r\n", content);
|
||||||
|
|
||||||
|
/* Generate the HTTP response */
|
||||||
|
printf("Content-length: %d\r\n", (int) strlen(content));
|
||||||
|
printf("Content-type: text/html\r\n\r\n");
|
||||||
|
printf("%s", content);
|
||||||
|
fflush(stdout);
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
243
server-exp2/common.c
Normal file
243
server-exp2/common.c
Normal file
@@ -0,0 +1,243 @@
|
|||||||
|
/* $begin common.c */
|
||||||
|
|
||||||
|
#include "common.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*********************************************************************
|
||||||
|
* The Rio package - robust I/O functions
|
||||||
|
**********************************************************************/
|
||||||
|
/*
|
||||||
|
* rio_readn - robustly read n bytes (unbuffered)
|
||||||
|
*/
|
||||||
|
/* $begin rio_readn */
|
||||||
|
ssize_t rio_readn(int fd, void *usrbuf, size_t n)
|
||||||
|
{
|
||||||
|
size_t nleft = n;
|
||||||
|
ssize_t nread;
|
||||||
|
char *bufp = usrbuf;
|
||||||
|
|
||||||
|
while (nleft > 0) {
|
||||||
|
if ((nread = read(fd, bufp, nleft)) < 0) {
|
||||||
|
if (errno == EINTR) /* interrupted by sig handler return */
|
||||||
|
nread = 0; /* and call read() again */
|
||||||
|
else
|
||||||
|
return -1; /* errno set by read() */
|
||||||
|
}
|
||||||
|
else if (nread == 0)
|
||||||
|
break; /* EOF */
|
||||||
|
nleft -= nread;
|
||||||
|
bufp += nread;
|
||||||
|
}
|
||||||
|
return (n - nleft); /* return >= 0 */
|
||||||
|
}
|
||||||
|
/* $end rio_readn */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* rio_writen - robustly write n bytes (unbuffered)
|
||||||
|
*/
|
||||||
|
/* $begin rio_writen */
|
||||||
|
ssize_t rio_writen(int fd, void *usrbuf, size_t n)
|
||||||
|
{
|
||||||
|
size_t nleft = n;
|
||||||
|
ssize_t nwritten;
|
||||||
|
char *bufp = usrbuf;
|
||||||
|
|
||||||
|
while (nleft > 0) {
|
||||||
|
if ((nwritten = write(fd, bufp, nleft)) <= 0) {
|
||||||
|
if (errno == EINTR) /* interrupted by sig handler return */
|
||||||
|
nwritten = 0; /* and call write() again */
|
||||||
|
else
|
||||||
|
return -1; /* errorno set by write() */
|
||||||
|
}
|
||||||
|
nleft -= nwritten;
|
||||||
|
bufp += nwritten;
|
||||||
|
}
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
/* $end rio_writen */
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* rio_read - This is a wrapper for the Unix read() function that
|
||||||
|
* transfers min(n, rio_cnt) bytes from an internal buffer to a user
|
||||||
|
* buffer, where n is the number of bytes requested by the user and
|
||||||
|
* rio_cnt is the number of unread bytes in the internal buffer. On
|
||||||
|
* entry, rio_read() refills the internal buffer via a call to
|
||||||
|
* read() if the internal buffer is empty.
|
||||||
|
*/
|
||||||
|
/* $begin rio_read */
|
||||||
|
static ssize_t rio_read(rio_t *rp, char *usrbuf, size_t n)
|
||||||
|
{
|
||||||
|
int cnt;
|
||||||
|
|
||||||
|
while (rp->rio_cnt <= 0) { /* refill if buf is empty */
|
||||||
|
rp->rio_cnt = read(rp->rio_fd, rp->rio_buf,
|
||||||
|
sizeof(rp->rio_buf));
|
||||||
|
if (rp->rio_cnt < 0) {
|
||||||
|
if (errno != EINTR) /* interrupted by sig handler return */
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
else if (rp->rio_cnt == 0) /* EOF */
|
||||||
|
return 0;
|
||||||
|
else
|
||||||
|
rp->rio_bufptr = rp->rio_buf; /* reset buffer ptr */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Copy min(n, rp->rio_cnt) bytes from internal buf to user buf */
|
||||||
|
cnt = n;
|
||||||
|
if (rp->rio_cnt < n)
|
||||||
|
cnt = rp->rio_cnt;
|
||||||
|
memcpy(usrbuf, rp->rio_bufptr, cnt);
|
||||||
|
rp->rio_bufptr += cnt;
|
||||||
|
rp->rio_cnt -= cnt;
|
||||||
|
return cnt;
|
||||||
|
}
|
||||||
|
/* $end rio_read */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* rio_readinitb - Associate a descriptor with a read buffer and reset buffer
|
||||||
|
*/
|
||||||
|
/* $begin rio_readinitb */
|
||||||
|
void rio_readinitb(rio_t *rp, int fd)
|
||||||
|
{
|
||||||
|
rp->rio_fd = fd;
|
||||||
|
rp->rio_cnt = 0;
|
||||||
|
rp->rio_bufptr = rp->rio_buf;
|
||||||
|
}
|
||||||
|
/* $end rio_readinitb */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* rio_readnb - Robustly read n bytes (buffered)
|
||||||
|
*/
|
||||||
|
/* $begin rio_readnb */
|
||||||
|
ssize_t rio_readnb(rio_t *rp, void *usrbuf, size_t n)
|
||||||
|
{
|
||||||
|
size_t nleft = n;
|
||||||
|
ssize_t nread;
|
||||||
|
char *bufp = usrbuf;
|
||||||
|
|
||||||
|
while (nleft > 0) {
|
||||||
|
if ((nread = rio_read(rp, bufp, nleft)) < 0) {
|
||||||
|
if (errno == EINTR) /* interrupted by sig handler return */
|
||||||
|
nread = 0; /* call read() again */
|
||||||
|
else
|
||||||
|
return -1; /* errno set by read() */
|
||||||
|
}
|
||||||
|
else if (nread == 0)
|
||||||
|
break; /* EOF */
|
||||||
|
nleft -= nread;
|
||||||
|
bufp += nread;
|
||||||
|
}
|
||||||
|
return (n - nleft); /* return >= 0 */
|
||||||
|
}
|
||||||
|
/* $end rio_readnb */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* rio_readlineb - robustly read a text line (buffered)
|
||||||
|
*/
|
||||||
|
/* $begin rio_readlineb */
|
||||||
|
ssize_t rio_readlineb(rio_t *rp, void *usrbuf, size_t maxlen)
|
||||||
|
{
|
||||||
|
int n, rc;
|
||||||
|
char c, *bufp = usrbuf;
|
||||||
|
|
||||||
|
for (n = 1; n < maxlen; n++) {
|
||||||
|
if ((rc = rio_read(rp, &c, 1)) == 1) {
|
||||||
|
*bufp++ = c;
|
||||||
|
if (c == '\n')
|
||||||
|
break;
|
||||||
|
} else if (rc == 0) {
|
||||||
|
if (n == 1)
|
||||||
|
return 0; /* EOF, no data read */
|
||||||
|
else
|
||||||
|
break; /* EOF, some data was read */
|
||||||
|
} else
|
||||||
|
return -1; /* error */
|
||||||
|
}
|
||||||
|
*bufp = 0;
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
/* $end rio_readlineb */
|
||||||
|
|
||||||
|
/**********************************
|
||||||
|
* Wrappers for robust I/O routines
|
||||||
|
**********************************/
|
||||||
|
|
||||||
|
|
||||||
|
/********************************
|
||||||
|
* Client/server helper functions
|
||||||
|
********************************/
|
||||||
|
/*
|
||||||
|
* open_client_sock - open connection to server at <hostname, port>
|
||||||
|
* and return a socket descriptor ready for reading and writing.
|
||||||
|
* Returns -1 and sets errno on Unix error.
|
||||||
|
* Returns -2 and sets h_errno on DNS (gethostbyname) error.
|
||||||
|
*/
|
||||||
|
/* $begin open_client_sock */
|
||||||
|
int open_client_sock(char *hostname, int port)
|
||||||
|
{
|
||||||
|
int client_sock;
|
||||||
|
struct hostent *hp;
|
||||||
|
struct sockaddr_in serveraddr;
|
||||||
|
|
||||||
|
if ((client_sock = socket(AF_INET, SOCK_STREAM, 0)) < 0)
|
||||||
|
return -1; /* check errno for cause of error */
|
||||||
|
|
||||||
|
/* Fill in the server's IP address and port */
|
||||||
|
if ((hp = gethostbyname(hostname)) == NULL)
|
||||||
|
return -2; /* check h_errno for cause of error */
|
||||||
|
bzero((char *) &serveraddr, sizeof(serveraddr));
|
||||||
|
serveraddr.sin_family = AF_INET;
|
||||||
|
bcopy((char *)hp->h_addr_list[0],
|
||||||
|
(char *)&serveraddr.sin_addr.s_addr, hp->h_length);
|
||||||
|
serveraddr.sin_port = htons(port);
|
||||||
|
|
||||||
|
/* Establish a connection with the server */
|
||||||
|
if (connect(client_sock, (SA *) &serveraddr, sizeof(serveraddr)) < 0)
|
||||||
|
return -1;
|
||||||
|
return client_sock;
|
||||||
|
}
|
||||||
|
/* $end open_client_sock */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* open_listen_sock - open and return a listening socket on port
|
||||||
|
* Returns -1 and sets errno on Unix error.
|
||||||
|
*/
|
||||||
|
/* $begin open_listen_sock */
|
||||||
|
int open_listen_sock(int port)
|
||||||
|
{
|
||||||
|
int listen_sock, optval=1;
|
||||||
|
struct sockaddr_in serveraddr;
|
||||||
|
|
||||||
|
/* Create a socket descriptor */
|
||||||
|
if ((listen_sock = socket(AF_INET, SOCK_STREAM, 0)) < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
/* Eliminates "Address already in use" error from bind. */
|
||||||
|
if (setsockopt(listen_sock, SOL_SOCKET, SO_REUSEADDR,
|
||||||
|
(const void *)&optval , sizeof(int)) < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
/* Listen_sock will be an endpoint for all requests to port
|
||||||
|
on any IP address for this host */
|
||||||
|
bzero((char *) &serveraddr, sizeof(serveraddr));
|
||||||
|
serveraddr.sin_family = AF_INET;
|
||||||
|
serveraddr.sin_addr.s_addr = htonl(INADDR_ANY);
|
||||||
|
serveraddr.sin_port = htons((unsigned short)port);
|
||||||
|
if (bind(listen_sock, (SA *)&serveraddr, sizeof(serveraddr)) < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
/* Make it a listening socket ready to accept connection requests */
|
||||||
|
if (listen(listen_sock, LISTENQ) < 0)
|
||||||
|
return -1;
|
||||||
|
return listen_sock;
|
||||||
|
}
|
||||||
|
/* $end open_listen_sock */
|
||||||
|
|
||||||
|
|
||||||
|
/* $end wrapper.c */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
78
server-exp2/common.h
Normal file
78
server-exp2/common.h
Normal file
@@ -0,0 +1,78 @@
|
|||||||
|
/* $begin common.h */
|
||||||
|
#ifndef __COMMON_H__
|
||||||
|
#define __COMMON_H__
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <setjmp.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/wait.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <sys/mman.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <math.h>
|
||||||
|
#include <pthread.h>
|
||||||
|
#include <semaphore.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <netdb.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
#include <limits.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/ipc.h>
|
||||||
|
#include <sys/msg.h>
|
||||||
|
#include <sys/shm.h>
|
||||||
|
#include <sys/sem.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <sys/prctl.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
/* Default file permissions are DEF_MODE & ~DEF_UMASK */
|
||||||
|
/* $begin createmasks */
|
||||||
|
#define DEF_MODE S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH
|
||||||
|
#define DEF_UMASK S_IWGRP|S_IWOTH
|
||||||
|
/* $end createmasks */
|
||||||
|
|
||||||
|
/* Simplifies calls to bind(), connect(), and accept() */
|
||||||
|
/* $begin sockaddrdef */
|
||||||
|
typedef struct sockaddr SA;
|
||||||
|
/* $end sockaddrdef */
|
||||||
|
|
||||||
|
/* Persistent state for the robust I/O (Rio) package */
|
||||||
|
/* $begin rio_t */
|
||||||
|
#define RIO_BUFSIZE 8192
|
||||||
|
typedef struct {
|
||||||
|
int rio_fd; /* descriptor for this internal buf */
|
||||||
|
int rio_cnt; /* unread bytes in internal buf */
|
||||||
|
char *rio_bufptr; /* next unread byte in internal buf */
|
||||||
|
char rio_buf[RIO_BUFSIZE]; /* internal buffer */
|
||||||
|
} rio_t;
|
||||||
|
/* $end rio_t */
|
||||||
|
|
||||||
|
/* External variables */
|
||||||
|
extern int h_errno; /* defined by BIND for DNS errors */
|
||||||
|
extern char **environ; /* defined by libc */
|
||||||
|
|
||||||
|
/* Misc constants */
|
||||||
|
#define MAXLINE 8192 /* max text line length */
|
||||||
|
#define MAXBUF 8192 /* max I/O buffer size */
|
||||||
|
#define LISTENQ 1024 /* second argument to listen() */
|
||||||
|
|
||||||
|
/* Rio (Robust I/O) package */
|
||||||
|
ssize_t rio_readn(int fd, void *usrbuf, size_t n);
|
||||||
|
ssize_t rio_writen(int fd, void *usrbuf, size_t n);
|
||||||
|
void rio_readinitb(rio_t *rp, int fd);
|
||||||
|
ssize_t rio_readnb(rio_t *rp, void *usrbuf, size_t n);
|
||||||
|
ssize_t rio_readlineb(rio_t *rp, void *usrbuf, size_t maxlen);
|
||||||
|
|
||||||
|
/* Client/server helper functions */
|
||||||
|
int open_client_sock(char *hostname, int portno);
|
||||||
|
int open_listen_sock(int portno);
|
||||||
|
|
||||||
|
#endif /* __COMMON_H__ */
|
||||||
|
/* $end common.h */
|
||||||
BIN
server-exp2/example.jpg
Normal file
BIN
server-exp2/example.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 189 KiB |
BIN
server-exp2/favicon.ico
Normal file
BIN
server-exp2/favicon.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 16 KiB |
13
server-exp2/index.html
Normal file
13
server-exp2/index.html
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<link rel="shortcut icon" href="favicon.ico" type="image/x-icon"/>
|
||||||
|
<title>the example web</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<H1>webserver test page</H1>
|
||||||
|
<p>
|
||||||
|
Not pretty but should prove that webserver works:-)
|
||||||
|
<p>
|
||||||
|
<IMG SRC="example.jpg">
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
200
server-exp2/perf.txt
Normal file
200
server-exp2/perf.txt
Normal file
@@ -0,0 +1,200 @@
|
|||||||
|
Flat profile:
|
||||||
|
|
||||||
|
Each sample counts as 0.01 seconds.
|
||||||
|
% cumulative self self total
|
||||||
|
time seconds seconds calls us/call us/call name
|
||||||
|
42.86 0.09 0.09 23039432 0.00 0.00 rio_read
|
||||||
|
28.57 0.15 0.06 15339432 0.00 0.01 rio_readlineb
|
||||||
|
9.52 0.17 0.02 100001 0.20 1.69 read_requesthdrs
|
||||||
|
9.52 0.19 0.02 100000 0.20 0.20 get_filetype
|
||||||
|
4.76 0.20 0.01 100001 0.10 2.10 process_trans
|
||||||
|
4.76 0.21 0.01 100001 0.10 0.10 rio_readinitb
|
||||||
|
0.00 0.21 0.00 200000 0.00 0.00 rio_writen
|
||||||
|
0.00 0.21 0.00 100000 0.00 0.20 feed_static
|
||||||
|
0.00 0.21 0.00 100000 0.00 0.00 is_static
|
||||||
|
0.00 0.21 0.00 100000 0.00 0.00 parse_static_uri
|
||||||
|
0.00 0.21 0.00 1 0.00 0.00 open_listen_sock
|
||||||
|
|
||||||
|
% the percentage of the total running time of the
|
||||||
|
time program used by this function.
|
||||||
|
|
||||||
|
cumulative a running sum of the number of seconds accounted
|
||||||
|
seconds for by this function and those listed above it.
|
||||||
|
|
||||||
|
self the number of seconds accounted for by this
|
||||||
|
seconds function alone. This is the major sort for this
|
||||||
|
listing.
|
||||||
|
|
||||||
|
calls the number of times this function was invoked, if
|
||||||
|
this function is profiled, else blank.
|
||||||
|
|
||||||
|
self the average number of milliseconds spent in this
|
||||||
|
ms/call function per call, if this function is profiled,
|
||||||
|
else blank.
|
||||||
|
|
||||||
|
total the average number of milliseconds spent in this
|
||||||
|
ms/call function and its descendents per call, if this
|
||||||
|
function is profiled, else blank.
|
||||||
|
|
||||||
|
name the name of the function. This is the minor sort
|
||||||
|
for this listing. The index shows the location of
|
||||||
|
the function in the gprof listing. If the index is
|
||||||
|
in parenthesis it shows where it would appear in
|
||||||
|
the gprof listing if it were to be printed.
|
||||||
|
|
||||||
|
Copyright (C) 2012-2024 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
Copying and distribution of this file, with or without modification,
|
||||||
|
are permitted in any medium without royalty provided the copyright
|
||||||
|
notice and this notice are preserved.
|
||||||
|
|
||||||
|
Call graph (explanation follows)
|
||||||
|
|
||||||
|
|
||||||
|
granularity: each sample hit covers 4 byte(s) for 4.76% of 0.21 seconds
|
||||||
|
|
||||||
|
index % time self children called name
|
||||||
|
0.01 0.20 100001/100001 main [2]
|
||||||
|
[1] 100.0 0.01 0.20 100001 process_trans [1]
|
||||||
|
0.02 0.15 100001/100001 read_requesthdrs [3]
|
||||||
|
0.00 0.02 100000/100000 feed_static [6]
|
||||||
|
0.01 0.00 100001/100001 rio_readinitb [8]
|
||||||
|
0.00 0.00 100001/15339432 rio_readlineb [4]
|
||||||
|
0.00 0.00 100000/100000 is_static [10]
|
||||||
|
0.00 0.00 100000/100000 parse_static_uri [11]
|
||||||
|
-----------------------------------------------
|
||||||
|
<spontaneous>
|
||||||
|
[2] 100.0 0.00 0.21 main [2]
|
||||||
|
0.01 0.20 100001/100001 process_trans [1]
|
||||||
|
0.00 0.00 1/1 open_listen_sock [12]
|
||||||
|
-----------------------------------------------
|
||||||
|
0.02 0.15 100001/100001 process_trans [1]
|
||||||
|
[3] 80.5 0.02 0.15 100001 read_requesthdrs [3]
|
||||||
|
0.06 0.09 15239431/15339432 rio_readlineb [4]
|
||||||
|
-----------------------------------------------
|
||||||
|
0.00 0.00 100001/15339432 process_trans [1]
|
||||||
|
0.06 0.09 15239431/15339432 read_requesthdrs [3]
|
||||||
|
[4] 71.4 0.06 0.09 15339432 rio_readlineb [4]
|
||||||
|
0.09 0.00 23039432/23039432 rio_read [5]
|
||||||
|
-----------------------------------------------
|
||||||
|
0.09 0.00 23039432/23039432 rio_readlineb [4]
|
||||||
|
[5] 42.9 0.09 0.00 23039432 rio_read [5]
|
||||||
|
-----------------------------------------------
|
||||||
|
0.00 0.02 100000/100000 process_trans [1]
|
||||||
|
[6] 9.5 0.00 0.02 100000 feed_static [6]
|
||||||
|
0.02 0.00 100000/100000 get_filetype [7]
|
||||||
|
0.00 0.00 200000/200000 rio_writen [9]
|
||||||
|
-----------------------------------------------
|
||||||
|
0.02 0.00 100000/100000 feed_static [6]
|
||||||
|
[7] 9.5 0.02 0.00 100000 get_filetype [7]
|
||||||
|
-----------------------------------------------
|
||||||
|
0.01 0.00 100001/100001 process_trans [1]
|
||||||
|
[8] 4.8 0.01 0.00 100001 rio_readinitb [8]
|
||||||
|
-----------------------------------------------
|
||||||
|
0.00 0.00 200000/200000 feed_static [6]
|
||||||
|
[9] 0.0 0.00 0.00 200000 rio_writen [9]
|
||||||
|
-----------------------------------------------
|
||||||
|
0.00 0.00 100000/100000 process_trans [1]
|
||||||
|
[10] 0.0 0.00 0.00 100000 is_static [10]
|
||||||
|
-----------------------------------------------
|
||||||
|
0.00 0.00 100000/100000 process_trans [1]
|
||||||
|
[11] 0.0 0.00 0.00 100000 parse_static_uri [11]
|
||||||
|
-----------------------------------------------
|
||||||
|
0.00 0.00 1/1 main [2]
|
||||||
|
[12] 0.0 0.00 0.00 1 open_listen_sock [12]
|
||||||
|
-----------------------------------------------
|
||||||
|
|
||||||
|
This table describes the call tree of the program, and was sorted by
|
||||||
|
the total amount of time spent in each function and its children.
|
||||||
|
|
||||||
|
Each entry in this table consists of several lines. The line with the
|
||||||
|
index number at the left hand margin lists the current function.
|
||||||
|
The lines above it list the functions that called this function,
|
||||||
|
and the lines below it list the functions this one called.
|
||||||
|
This line lists:
|
||||||
|
index A unique number given to each element of the table.
|
||||||
|
Index numbers are sorted numerically.
|
||||||
|
The index number is printed next to every function name so
|
||||||
|
it is easier to look up where the function is in the table.
|
||||||
|
|
||||||
|
% time This is the percentage of the `total' time that was spent
|
||||||
|
in this function and its children. Note that due to
|
||||||
|
different viewpoints, functions excluded by options, etc,
|
||||||
|
these numbers will NOT add up to 100%.
|
||||||
|
|
||||||
|
self This is the total amount of time spent in this function.
|
||||||
|
|
||||||
|
children This is the total amount of time propagated into this
|
||||||
|
function by its children.
|
||||||
|
|
||||||
|
called This is the number of times the function was called.
|
||||||
|
If the function called itself recursively, the number
|
||||||
|
only includes non-recursive calls, and is followed by
|
||||||
|
a `+' and the number of recursive calls.
|
||||||
|
|
||||||
|
name The name of the current function. The index number is
|
||||||
|
printed after it. If the function is a member of a
|
||||||
|
cycle, the cycle number is printed between the
|
||||||
|
function's name and the index number.
|
||||||
|
|
||||||
|
|
||||||
|
For the function's parents, the fields have the following meanings:
|
||||||
|
|
||||||
|
self This is the amount of time that was propagated directly
|
||||||
|
from the function into this parent.
|
||||||
|
|
||||||
|
children This is the amount of time that was propagated from
|
||||||
|
the function's children into this parent.
|
||||||
|
|
||||||
|
called This is the number of times this parent called the
|
||||||
|
function `/' the total number of times the function
|
||||||
|
was called. Recursive calls to the function are not
|
||||||
|
included in the number after the `/'.
|
||||||
|
|
||||||
|
name This is the name of the parent. The parent's index
|
||||||
|
number is printed after it. If the parent is a
|
||||||
|
member of a cycle, the cycle number is printed between
|
||||||
|
the name and the index number.
|
||||||
|
|
||||||
|
If the parents of the function cannot be determined, the word
|
||||||
|
`<spontaneous>' is printed in the `name' field, and all the other
|
||||||
|
fields are blank.
|
||||||
|
|
||||||
|
For the function's children, the fields have the following meanings:
|
||||||
|
|
||||||
|
self This is the amount of time that was propagated directly
|
||||||
|
from the child into the function.
|
||||||
|
|
||||||
|
children This is the amount of time that was propagated from the
|
||||||
|
child's children to the function.
|
||||||
|
|
||||||
|
called This is the number of times the function called
|
||||||
|
this child `/' the total number of times the child
|
||||||
|
was called. Recursive calls by the child are not
|
||||||
|
listed in the number after the `/'.
|
||||||
|
|
||||||
|
name This is the name of the child. The child's index
|
||||||
|
number is printed after it. If the child is a
|
||||||
|
member of a cycle, the cycle number is printed
|
||||||
|
between the name and the index number.
|
||||||
|
|
||||||
|
If there are any cycles (circles) in the call graph, there is an
|
||||||
|
entry for the cycle-as-a-whole. This entry shows who called the
|
||||||
|
cycle (as parents) and the members of the cycle (as children.)
|
||||||
|
The `+' recursive calls entry shows the number of function calls that
|
||||||
|
were internal to the cycle, and the calls entry for each member shows,
|
||||||
|
for that member, how many times it was called from other members of
|
||||||
|
the cycle.
|
||||||
|
|
||||||
|
Copyright (C) 2012-2024 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
Copying and distribution of this file, with or without modification,
|
||||||
|
are permitted in any medium without royalty provided the copyright
|
||||||
|
notice and this notice are preserved.
|
||||||
|
|
||||||
|
Index by function name
|
||||||
|
|
||||||
|
[6] feed_static [11] parse_static_uri [8] rio_readinitb
|
||||||
|
[7] get_filetype [1] process_trans [4] rio_readlineb
|
||||||
|
[10] is_static [3] read_requesthdrs [9] rio_writen
|
||||||
|
[12] open_listen_sock [5] rio_read (common.c)
|
||||||
6
server-exp2/t1.txt
Normal file
6
server-exp2/t1.txt
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
hello
|
||||||
|
world
|
||||||
|
dgut
|
||||||
|
computer
|
||||||
|
Hello
|
||||||
|
WORLD
|
||||||
6
server-exp2/t2.txt
Normal file
6
server-exp2/t2.txt
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
hello
|
||||||
|
world
|
||||||
|
dgut
|
||||||
|
computer
|
||||||
|
Hello
|
||||||
|
WORLD
|
||||||
45
server-exp2/taskline.c
Normal file
45
server-exp2/taskline.c
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
/* task pool management fucntions */
|
||||||
|
/* task_pool_init */
|
||||||
|
|
||||||
|
#include "common.h"
|
||||||
|
#include "taskline.h"
|
||||||
|
void task_line_init(task_line_t *tlp, int n)
|
||||||
|
{
|
||||||
|
tlp->taskp = calloc(n, sizeof(task_t));
|
||||||
|
tlp->cnt = n; /* socks holds max of n items */
|
||||||
|
tlp->inpos= tlp->outpos = 0; /* Empty socks iff inpos== outpos */
|
||||||
|
sem_init(&tlp->mutex, 0, 1); /* Binary semaphore for locking */
|
||||||
|
sem_init(&tlp->avail, 0, tlp->cnt);/* Initially, socks has cnt empty cell */
|
||||||
|
sem_init(&tlp->ready, 0, 0); /* Initially, socks has zero data items */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Clean up task line */
|
||||||
|
void task_line_deinit(task_line_t *tlp)
|
||||||
|
{
|
||||||
|
free(tlp->taskp);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Insert item onto the rear of task line */
|
||||||
|
void task_insert (task_line_t *tlp, task_t item)
|
||||||
|
{ sem_wait(&tlp->avail); /* Wait for available cell */
|
||||||
|
sem_wait(&tlp->mutex); /* Lock the shared variable inpos pointer */
|
||||||
|
tlp->taskp[tlp->inpos] = item; /* Insert the item */
|
||||||
|
tlp->inpos =(tlp-> inpos +1)%(tlp->cnt); /* adjuset inpos point */
|
||||||
|
sem_post(&tlp->mutex); /* Unlock the buffer */
|
||||||
|
sem_post(&tlp->ready); /* Announce available item */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Remove and return the first item from task_pool */
|
||||||
|
task_t task_remove(task_line_t *tlp)
|
||||||
|
{
|
||||||
|
task_t item;
|
||||||
|
sem_wait(&tlp->ready); /* Wait for available item */
|
||||||
|
sem_wait(&tlp->mutex); /* Lock the shared pointer variable tp->outpos */
|
||||||
|
item = tlp->taskp[tlp->outpos]; /* Remove the item */
|
||||||
|
tlp->outpos=(tlp->outpos+1)%(tlp->cnt); /* adjuset outpos point */
|
||||||
|
sem_post(&tlp->avail); /* Announce available slot */
|
||||||
|
sem_post(&tlp->mutex); /* Unlock the shared pointer variable tp->outpos */
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
|
||||||
20
server-exp2/taskline.h
Normal file
20
server-exp2/taskline.h
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
typedef struct _task_t {
|
||||||
|
int conn_sock; //客户连接socket
|
||||||
|
int hit; //第几个客户
|
||||||
|
} task_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
task_t *taskp; /* Buffer array */
|
||||||
|
int cnt; /* Maximum number of cell */
|
||||||
|
int inpos; /* buf[inpos] is first available cell */
|
||||||
|
int outpos; /* buf[outpos] is fist item */
|
||||||
|
sem_t mutex; /* Protects accesses to socks */
|
||||||
|
sem_t avail; /* Counts available cells */
|
||||||
|
sem_t ready; /* Counts ready items */
|
||||||
|
} task_line_t;
|
||||||
|
|
||||||
|
/* task line wrapper functions */
|
||||||
|
void task_line_init(task_line_t *tlp, int n);
|
||||||
|
void task_line_deinit(task_line_t *tlp);
|
||||||
|
void task_insert(task_line_t *tlp, task_t item);
|
||||||
|
task_t task_remove(task_line_t *tlp);
|
||||||
8
server-exp2/test.html
Normal file
8
server-exp2/test.html
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>a simple page for testing tiny</title>
|
||||||
|
<head>
|
||||||
|
<body>
|
||||||
|
Hello World
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
BIN
server-exp2/togglec
Executable file
BIN
server-exp2/togglec
Executable file
Binary file not shown.
30
server-exp2/togglec.c
Normal file
30
server-exp2/togglec.c
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
#include "common.h"
|
||||||
|
|
||||||
|
int main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
int client_sock, port;
|
||||||
|
char *host, buf[MAXLINE];
|
||||||
|
rio_t rio;
|
||||||
|
|
||||||
|
if (argc != 3) {
|
||||||
|
fprintf(stderr, "usage: %s <host><port>\n", argv[0]);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
host = argv[1];
|
||||||
|
port = atoi(argv[2]);
|
||||||
|
|
||||||
|
client_sock = open_client_sock(host, port);
|
||||||
|
if(client_sock==-1) {
|
||||||
|
fputs("Error to connect the Server\n",stdout);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
while (fgets(buf, MAXLINE, stdin) != NULL) {
|
||||||
|
//sleep(1);
|
||||||
|
send(client_sock, buf, strlen(buf),0);
|
||||||
|
recv(client_sock, buf, MAXLINE,0);
|
||||||
|
fputs(buf, stdout);
|
||||||
|
}
|
||||||
|
close(client_sock);
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
6
server-exp2/togglecm
Normal file
6
server-exp2/togglecm
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
for i in {1..20}
|
||||||
|
do
|
||||||
|
./togglec localhost 12345 < $1
|
||||||
|
sleep 1
|
||||||
|
done
|
||||||
|
|
||||||
BIN
server-exp2/togglesp
Executable file
BIN
server-exp2/togglesp
Executable file
Binary file not shown.
82
server-exp2/togglesp.c
Normal file
82
server-exp2/togglesp.c
Normal file
@@ -0,0 +1,82 @@
|
|||||||
|
#include "common.h"
|
||||||
|
|
||||||
|
void sigchld_handler(int sig)
|
||||||
|
{
|
||||||
|
while (waitpid(-1, 0, WNOHANG) > 0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef void (*sighandler_t) (int sig) ;
|
||||||
|
|
||||||
|
void Signal(int sig, sighandler_t handler){
|
||||||
|
struct sigaction sa;
|
||||||
|
sa.sa_handler = sigchld_handler;
|
||||||
|
sigemptyset(&sa.sa_mask);
|
||||||
|
sa.sa_flags = SA_RESTART; // 确保被信号中断的系统调用自动重启
|
||||||
|
sigaction(SIGCHLD, &sa, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
void toggle(int conn_sock,int hit)
|
||||||
|
{
|
||||||
|
size_t n; int i,no=0;
|
||||||
|
char buf[MAXLINE];
|
||||||
|
|
||||||
|
printf("第%d个客户通信开始\n",hit);
|
||||||
|
while((n =recv(conn_sock, buf, MAXLINE,0))> 0) {
|
||||||
|
printf("toggle服务器收到第%d个客户第%d个消息,长度为%d字节\n", hit,++no,(int)n);
|
||||||
|
|
||||||
|
for(i=0; i<n; i++)
|
||||||
|
if(isupper(buf[i]))
|
||||||
|
buf[i]=tolower(buf[i]);
|
||||||
|
else if(islower(buf[i]))
|
||||||
|
buf[i]=toupper(buf[i]);
|
||||||
|
|
||||||
|
send (conn_sock, buf, n, 0);
|
||||||
|
}
|
||||||
|
printf("第%d个客户通信结束\n",hit);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
int listen_sock, conn_sock, port;
|
||||||
|
struct sockaddr_in clientaddr;
|
||||||
|
struct hostent *hp;
|
||||||
|
char *haddrp;
|
||||||
|
int hit;
|
||||||
|
|
||||||
|
socklen_t clientlen=sizeof(struct sockaddr_in);
|
||||||
|
|
||||||
|
if (argc != 2) {
|
||||||
|
fprintf(stderr, "usage: %s <port>\n", argv[0]);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
port = atoi(argv[1]);
|
||||||
|
|
||||||
|
//设置SIGHLD的信号处理函数,用于收割结束的子进程
|
||||||
|
Signal(SIGCHLD, sigchld_handler);
|
||||||
|
|
||||||
|
listen_sock = open_listen_sock(port);
|
||||||
|
|
||||||
|
if( listen_sock==-1) {
|
||||||
|
printf("端口号%d繁忙\n",port);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
for(hit=1; ; hit++) {
|
||||||
|
conn_sock = accept(listen_sock, (SA *) &clientaddr, &clientlen);
|
||||||
|
|
||||||
|
/* determine the domain name and IP address of the client */
|
||||||
|
hp = gethostbyaddr((const char *)&clientaddr.sin_addr.s_addr,
|
||||||
|
sizeof(clientaddr.sin_addr.s_addr), AF_INET);
|
||||||
|
haddrp = inet_ntoa(clientaddr.sin_addr);
|
||||||
|
printf("server connected to %s (%s)\n", hp->h_name, haddrp);
|
||||||
|
|
||||||
|
if (fork() == 0) {
|
||||||
|
close(listen_sock); /* Child process closes its listening socket */
|
||||||
|
toggle(conn_sock,hit); /* Child process services client */
|
||||||
|
close(conn_sock); /* Child process closes connection with client */
|
||||||
|
exit(0); /* Child process exits */
|
||||||
|
}
|
||||||
|
close(conn_sock); /* Parent closes connected socket (important!) */
|
||||||
|
}
|
||||||
|
}
|
||||||
BIN
server-exp2/togglest
Executable file
BIN
server-exp2/togglest
Executable file
Binary file not shown.
85
server-exp2/togglest.c
Normal file
85
server-exp2/togglest.c
Normal file
@@ -0,0 +1,85 @@
|
|||||||
|
#include "common.h"
|
||||||
|
|
||||||
|
void toggle(int conn_sock, int hit);
|
||||||
|
void *serve_client(void *vargp);
|
||||||
|
|
||||||
|
typedef struct _client_data_t {
|
||||||
|
int conn_sock; //客户连接socket
|
||||||
|
int hit; //第几个客户
|
||||||
|
} client_data_t;
|
||||||
|
|
||||||
|
int main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
int listen_sock, conn_sock, port,*conn_sock_p ;
|
||||||
|
struct sockaddr_in clientaddr;
|
||||||
|
struct hostent *hp;
|
||||||
|
char *haddrp;
|
||||||
|
client_data_t *cdp; //连接客户信息
|
||||||
|
int hit; //连接客户计数
|
||||||
|
|
||||||
|
socklen_t clientlen=sizeof(struct sockaddr_in);
|
||||||
|
|
||||||
|
pthread_t tid;
|
||||||
|
|
||||||
|
if (argc != 2) {
|
||||||
|
fprintf(stderr, "usage: %s <port>\n", argv[0]);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
port = atoi(argv[1]);
|
||||||
|
|
||||||
|
listen_sock = open_listen_sock(port);
|
||||||
|
if( listen_sock==-1) {
|
||||||
|
printf("端口号%d繁忙\n",port);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (hit=1; ; hit++) {
|
||||||
|
cdp = malloc(sizeof(client_data_t));
|
||||||
|
cdp->conn_sock = accept(listen_sock, (SA *) &clientaddr, &clientlen);
|
||||||
|
cdp->hit=hit;
|
||||||
|
|
||||||
|
/* determine the domain name and IP address of the client */
|
||||||
|
hp = gethostbyaddr((const char *)&clientaddr.sin_addr.s_addr,
|
||||||
|
sizeof(clientaddr.sin_addr.s_addr), AF_INET);
|
||||||
|
haddrp = inet_ntoa(clientaddr.sin_addr);
|
||||||
|
printf("server connected to %s (%s)\n", hp->h_name, haddrp);
|
||||||
|
|
||||||
|
pthread_create(&tid, NULL, serve_client, (void *)cdp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* thread routine */
|
||||||
|
void * serve_client (void *vargp)
|
||||||
|
{
|
||||||
|
int hit,conn_sock;
|
||||||
|
client_data_t cd;
|
||||||
|
cd = *(client_data_t *)vargp;
|
||||||
|
|
||||||
|
pthread_detach(pthread_self());
|
||||||
|
free(vargp);
|
||||||
|
toggle(cd.conn_sock,cd.hit);
|
||||||
|
|
||||||
|
close(conn_sock);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void toggle(int conn_sock,int hit)
|
||||||
|
{
|
||||||
|
size_t n; int i,no=0;
|
||||||
|
char buf[MAXLINE];
|
||||||
|
|
||||||
|
printf("第%d个客户通信开始\n",hit);
|
||||||
|
while((n =recv(conn_sock, buf, MAXLINE,0))> 0) {
|
||||||
|
printf("toggle服务器收到第%d个客户第%d个消息,长度为%d字节\n", hit,++no,(int)n);
|
||||||
|
|
||||||
|
for(i=0; i<n; i++)
|
||||||
|
if(isupper(buf[i]))
|
||||||
|
buf[i]=tolower(buf[i]);
|
||||||
|
else if(islower(buf[i]))
|
||||||
|
buf[i]=toupper(buf[i]);
|
||||||
|
|
||||||
|
send (conn_sock, buf, n, 0);
|
||||||
|
}
|
||||||
|
printf("第%d个客户通信结束\n",hit);
|
||||||
|
}
|
||||||
|
|
||||||
104
server-exp2/togglest_pool.c
Normal file
104
server-exp2/togglest_pool.c
Normal file
@@ -0,0 +1,104 @@
|
|||||||
|
#include "common.h"
|
||||||
|
#include "pool.h"
|
||||||
|
|
||||||
|
#define NTHREADS 4
|
||||||
|
#define SBUFSIZE 16
|
||||||
|
|
||||||
|
void toggle(int conn_sock,int hit);
|
||||||
|
void *serve_client(void *vargp);
|
||||||
|
|
||||||
|
void toggle(int conn_sock,int hit)
|
||||||
|
{
|
||||||
|
size_t n; int i,no=0;
|
||||||
|
char buf[MAXLINE];
|
||||||
|
|
||||||
|
//printf("线程%d服务第%d个客户请求通信开始\n",tid,hit);
|
||||||
|
while((n =recv(conn_sock, buf, MAXLINE,0))> 0) {
|
||||||
|
printf("toggle服务器收到第%d个客户第%d个消息,长度为%d字节\n", hit,++no,(int)n);
|
||||||
|
|
||||||
|
for(i=0; i<n; i++)
|
||||||
|
if(isupper(buf[i]))
|
||||||
|
buf[i]=tolower(buf[i]);
|
||||||
|
else if(islower(buf[i]))
|
||||||
|
buf[i]=toupper(buf[i]);
|
||||||
|
sleep(1);
|
||||||
|
send (conn_sock, buf, n, 0);
|
||||||
|
}
|
||||||
|
//printf("线程%d服务第%d个客户请求通信结束\n",tid,hit);
|
||||||
|
}
|
||||||
|
|
||||||
|
//示例任务
|
||||||
|
void handle_request(int sock, int taskid, int tid) {
|
||||||
|
|
||||||
|
printf("线程%d服务第%d个客户通信开始\n",tid,taskid);
|
||||||
|
//usleep(1);
|
||||||
|
toggle(sock,taskid);
|
||||||
|
printf("线程%d服务第%d个客户通信结束\n",tid,taskid);
|
||||||
|
close(sock);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char **argv) {
|
||||||
|
|
||||||
|
int listen_sock, conn_sock, port,i;
|
||||||
|
struct sockaddr_in clientaddr;
|
||||||
|
struct hostent *hp;
|
||||||
|
char *haddrp;
|
||||||
|
int hit;
|
||||||
|
|
||||||
|
int nth[NTHREADS];
|
||||||
|
|
||||||
|
socklen_t clientlen=sizeof(struct sockaddr_in);
|
||||||
|
|
||||||
|
pthread_t tid;
|
||||||
|
|
||||||
|
if (argc != 2) {
|
||||||
|
fprintf(stderr, "usage: %s <port>\n", argv[0]);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
listen_sock = open_listen_sock(port);
|
||||||
|
if( listen_sock==-1) {
|
||||||
|
printf("端口号%d繁忙\n",port);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
port = atoi(argv[1]);
|
||||||
|
|
||||||
|
listen_sock = open_listen_sock(port);
|
||||||
|
if( listen_sock==-1) {
|
||||||
|
printf("端口号%d繁忙\n",port);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("start main\n");
|
||||||
|
// 初始化线程池
|
||||||
|
threadpool* pool = initThreadPool(NTHREADS);
|
||||||
|
|
||||||
|
// 创建示例任务并将其添加到线程池
|
||||||
|
for (hit=1; ; hit++) {
|
||||||
|
conn_sock = accept(listen_sock, (SA *) &clientaddr, &clientlen);
|
||||||
|
|
||||||
|
/* determine the domain name and IP address of the client */
|
||||||
|
hp = gethostbyaddr((const char *)&clientaddr.sin_addr.s_addr,
|
||||||
|
sizeof(clientaddr.sin_addr.s_addr), AF_INET);
|
||||||
|
haddrp = inet_ntoa(clientaddr.sin_addr);
|
||||||
|
//printf("server connected to %s (%s)\n", hp->h_name, haddrp);
|
||||||
|
|
||||||
|
task* new_task = (task*)malloc(sizeof(task));
|
||||||
|
new_task->function = handle_request; // 假设任务函数为 toggle
|
||||||
|
new_task->taskid = hit; // 任务参数,假设为 socket fd 或其他参数
|
||||||
|
new_task->sock=conn_sock;
|
||||||
|
|
||||||
|
addTaskToThreadPool(pool, new_task); /* Insert conn_sock in task pool */
|
||||||
|
}
|
||||||
|
|
||||||
|
// 等待线程池中的所有任务执行完毕
|
||||||
|
waitThreadPool(pool);
|
||||||
|
|
||||||
|
// 销毁线程池
|
||||||
|
destroyThreadPool(pool);
|
||||||
|
|
||||||
|
printf("stop main\n");
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
BIN
server-exp2/togglest_pre
Executable file
BIN
server-exp2/togglest_pre
Executable file
Binary file not shown.
100
server-exp2/togglest_pre.c
Normal file
100
server-exp2/togglest_pre.c
Normal file
@@ -0,0 +1,100 @@
|
|||||||
|
#include "common.h"
|
||||||
|
#include "taskline.h"
|
||||||
|
|
||||||
|
#define NTHREADS 4
|
||||||
|
#define SBUFSIZE 16
|
||||||
|
|
||||||
|
void toggle(int conn_sock,int hit);
|
||||||
|
void *handle_request(void *vargp);
|
||||||
|
|
||||||
|
task_line_t tlp; /* task pool: shared buffer of connected descriptors */
|
||||||
|
|
||||||
|
int main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
int listen_sock, conn_sock, port,i;
|
||||||
|
struct sockaddr_in clientaddr;
|
||||||
|
struct hostent *hp;
|
||||||
|
char *haddrp;
|
||||||
|
int hit;
|
||||||
|
task_t item; //连接客户信息:socket和客户编号
|
||||||
|
int nth[NTHREADS];
|
||||||
|
|
||||||
|
socklen_t clientlen=sizeof(struct sockaddr_in);
|
||||||
|
|
||||||
|
pthread_t tid;
|
||||||
|
|
||||||
|
if (argc != 2) {
|
||||||
|
fprintf(stderr, "usage: %s <port>\n", argv[0]);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
listen_sock = open_listen_sock(port);
|
||||||
|
if( listen_sock==-1) {
|
||||||
|
printf("端口号%d繁忙\n",port);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
port = atoi(argv[1]);
|
||||||
|
task_line_init(&tlp, SBUFSIZE);
|
||||||
|
|
||||||
|
listen_sock = open_listen_sock(port);
|
||||||
|
if( listen_sock==-1) {
|
||||||
|
printf("端口号%d繁忙\n",port);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < NTHREADS; i++) { /* Create worker threads */
|
||||||
|
nth[i]=i;
|
||||||
|
pthread_create(&tid, NULL, handle_request, (void *)&nth[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (hit=1; ; hit++) {
|
||||||
|
item.conn_sock = accept(listen_sock, (SA *) &clientaddr, &clientlen);
|
||||||
|
item.hit=hit;
|
||||||
|
|
||||||
|
/* determine the domain name and IP address of the client */
|
||||||
|
hp = gethostbyaddr((const char *)&clientaddr.sin_addr.s_addr,
|
||||||
|
sizeof(clientaddr.sin_addr.s_addr), AF_INET);
|
||||||
|
haddrp = inet_ntoa(clientaddr.sin_addr);
|
||||||
|
printf("server connected to %s (%s)\n", hp->h_name, haddrp);
|
||||||
|
|
||||||
|
task_insert(&tlp, item); /* Insert conn_sock in task pool */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void *handle_request(void *vargp)
|
||||||
|
{
|
||||||
|
int tid=*(int*) vargp;
|
||||||
|
task_t item;
|
||||||
|
pthread_detach(pthread_self());
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
item=task_remove(&tlp); /* Remove a task from task line */
|
||||||
|
|
||||||
|
printf("线程%d服务第%d个客户通信开始\n",tid,item.hit);
|
||||||
|
|
||||||
|
toggle(item.conn_sock,item.hit); /* Serve client */
|
||||||
|
close(item.conn_sock);
|
||||||
|
|
||||||
|
printf("线程%d服务第%d个客户通信结束\n",tid,item.hit);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void toggle(int conn_sock,int hit)
|
||||||
|
{
|
||||||
|
size_t n; int i,no=0;
|
||||||
|
char buf[MAXLINE];
|
||||||
|
|
||||||
|
while((n =recv(conn_sock, buf, MAXLINE,0))> 0) {
|
||||||
|
printf("toggle服务器收到第%d个客户第%d个消息,长度为%d字节\n", hit,++no,(int)n);
|
||||||
|
|
||||||
|
for(i=0; i<n; i++)
|
||||||
|
if(isupper(buf[i]))
|
||||||
|
buf[i]=tolower(buf[i]);
|
||||||
|
else if(islower(buf[i]))
|
||||||
|
buf[i]=toupper(buf[i]);
|
||||||
|
|
||||||
|
send (conn_sock, buf, n, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
2
server-exp2/urls
Normal file
2
server-exp2/urls
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
http://127.0.0.1:8088/index.html
|
||||||
|
http://127.0.0.1:8088/test.html
|
||||||
BIN
server-exp2/webclient
Executable file
BIN
server-exp2/webclient
Executable file
Binary file not shown.
55
server-exp2/webclient.c
Normal file
55
server-exp2/webclient.c
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
#include <arpa/inet.h> // 提供IP地址转换函数
|
||||||
|
#include <netinet/in.h> // 提供套接字地址结构定义
|
||||||
|
#include <stdio.h> // 标准输入输出
|
||||||
|
#include <stdlib.h> // 标准库函数,如exit()
|
||||||
|
#include <string.h> // 字符串操作函数
|
||||||
|
#include <sys/socket.h> // 套接字相关函数
|
||||||
|
#include <sys/types.h> // 数据类型定义
|
||||||
|
#include <unistd.h> // POSIX API,如read()和write()
|
||||||
|
|
||||||
|
//#define PORT 8181 /* 目标服务器的端口号 */
|
||||||
|
//#define IP_ADDRESS "192.168.0.8" /* 目标服务器的IP地址 */
|
||||||
|
#define BUFSIZE 8196 /* 缓冲区大小 */
|
||||||
|
|
||||||
|
char *command = "GET /index.html HTTP/1.0 \r\n\r\n"; /* HTTP GET 请求命令 */
|
||||||
|
|
||||||
|
// 错误处理函数,打印错误信息并退出程序
|
||||||
|
void pexit(char *msg) {
|
||||||
|
perror(msg); // 打印错误信息
|
||||||
|
exit(1); // 退出程序
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char *argv[]) {//客户端启动命令为"./client 127.0.0.1 8088",argv[1]是IP地址,argv[2]是端口号8088
|
||||||
|
int i, sockfd; // sockfd是套接字文件描述符
|
||||||
|
char buffer[BUFSIZE]; // 用于存储从服务器接收的数据
|
||||||
|
struct sockaddr_in serv_addr; // 定义服务器地址结构
|
||||||
|
|
||||||
|
// 打印尝试连接服务器的信息
|
||||||
|
printf("客户端尝试连接到 %s 和端口 %s\n", argv[1], argv[2]);
|
||||||
|
|
||||||
|
// 创建套接字,使用IPv4和TCP协议
|
||||||
|
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) pexit("socket() 创建失败");
|
||||||
|
|
||||||
|
// 配置服务器地址
|
||||||
|
serv_addr.sin_family = AF_INET; // 地址族为IPv4
|
||||||
|
serv_addr.sin_addr.s_addr = inet_addr(argv[1]); // 设置服务器IP地址,如"127.0.0.1"
|
||||||
|
serv_addr.sin_port = htons(atoi(argv[2])); // 设置服务器端口号,如"8088"
|
||||||
|
|
||||||
|
// 尝试连接到服务器
|
||||||
|
if (connect(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0)
|
||||||
|
pexit("connect() 连接失败");
|
||||||
|
|
||||||
|
// 发送HTTP GET请求到服务器
|
||||||
|
printf("发送字节数=%ld %s\n", strlen(command), command);
|
||||||
|
if (write(sockfd, command, strlen(command)) < 0) pexit("write() 发送请求失败");
|
||||||
|
|
||||||
|
// 循环读取服务器返回的数据,并输出到标准输出
|
||||||
|
while ((i = read(sockfd, buffer, BUFSIZE)) > 0) {
|
||||||
|
if (write(1, buffer, i) < 0) // 1表示标准输出
|
||||||
|
pexit("write() 输出到标准输出失败");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 关闭套接字,释放资源
|
||||||
|
close(sockfd);
|
||||||
|
return 0; // 程序正常退出
|
||||||
|
}
|
||||||
BIN
server-exp2/weblet
Executable file
BIN
server-exp2/weblet
Executable file
Binary file not shown.
265
server-exp2/weblet.c
Normal file
265
server-exp2/weblet.c
Normal file
@@ -0,0 +1,265 @@
|
|||||||
|
#include "common.h"
|
||||||
|
|
||||||
|
void process_trans(int fd,int hit);
|
||||||
|
void read_requesthdrs(rio_t *rp,int hit,int nrh);
|
||||||
|
int is_static(char *uri);
|
||||||
|
void parse_static_uri(char *uri, char *filename);
|
||||||
|
void parse_dynamic_uri(char *uri, char *filename, char *cgiargs);
|
||||||
|
void feed_static(int fd, char *filename, int filesize);
|
||||||
|
void get_filetype(char *filename, char *filetype);
|
||||||
|
void feed_dynamic(int fd, char *filename, char *cgiargs);
|
||||||
|
void error_request(int fd, char *cause, char *errnum,
|
||||||
|
char *shortmsg, char *description);
|
||||||
|
|
||||||
|
/* 支持的文件扩展名及其对应的MIME类型 */
|
||||||
|
struct {
|
||||||
|
char *ext; // 文件扩展名
|
||||||
|
char *filetype; // MIME类型
|
||||||
|
} extensions[] = {
|
||||||
|
{".gif", "image/gif"},
|
||||||
|
{".jpg", "image/jpg"},
|
||||||
|
{".jpeg", "image/jpeg"},
|
||||||
|
{".png", "image/png"},
|
||||||
|
{".ico", "image/ico"},
|
||||||
|
{".zip", "image/zip"},
|
||||||
|
{".gz", "image/gz"},
|
||||||
|
{".tar", "image/tar"},
|
||||||
|
{".htm", "text/html"},
|
||||||
|
{".html", "text/html"},
|
||||||
|
{0, 0} // 结束标志
|
||||||
|
};
|
||||||
|
|
||||||
|
/* 调试模式宏定义 */
|
||||||
|
#ifdef DEBUG
|
||||||
|
#define printf2(format, var) printf(format,var)
|
||||||
|
#define printf3(format,var1,var2) printf(format,var1,var2)
|
||||||
|
#else
|
||||||
|
#define printf2(format, var)
|
||||||
|
#define printf3(format,var1,var2)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* 全局变量说明 */
|
||||||
|
|
||||||
|
|
||||||
|
/* Ctrl+C信号处理函数 */
|
||||||
|
void ctrlc_handler(int sig)
|
||||||
|
{
|
||||||
|
printf("您按下了Ctrl+C终止了Web服务器\n");
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 主函数:监听端口并处理客户端连接 */
|
||||||
|
|
||||||
|
int main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
int listen_sock, conn_sock, port;
|
||||||
|
int hit; // 请求计数器
|
||||||
|
socklen_t clientlen;
|
||||||
|
struct sockaddr_in clientaddr;
|
||||||
|
|
||||||
|
/* 检查命令行参数 */
|
||||||
|
if (argc != 2) {
|
||||||
|
fprintf(stderr, "用法: %s <端口号>\n", argv[0]);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
port = atoi(argv[1]);
|
||||||
|
|
||||||
|
listen_sock = open_listen_sock(port);
|
||||||
|
for (hit=1; ; hit++) { //hit为第几次请求,或第几次http事务
|
||||||
|
clientlen = sizeof(clientaddr);
|
||||||
|
conn_sock = accept(listen_sock, (SA *)&clientaddr, &clientlen);
|
||||||
|
process_trans(conn_sock,hit); // 处理HTTP事务
|
||||||
|
close(conn_sock);
|
||||||
|
}
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 处理HTTP事务的核心函数 */
|
||||||
|
void process_trans(int fd,int hit)
|
||||||
|
{
|
||||||
|
int static_flag; // 是否为静态资源标志
|
||||||
|
struct stat sbuf; // 文件状态信息
|
||||||
|
char buf[MAXLINE], method[MAXLINE], uri[MAXLINE], version[MAXLINE];
|
||||||
|
char filename[MAXLINE], cgiargs[MAXLINE];
|
||||||
|
rio_t rio;
|
||||||
|
int rhn=0; // 请求头计数器
|
||||||
|
|
||||||
|
/* 设置Ctrl+C信号处理 */
|
||||||
|
if(signal(SIGINT,ctrlc_handler)==SIG_ERR)
|
||||||
|
(void)printf("错误: 无法设置SIGINT信号处理\n");
|
||||||
|
|
||||||
|
printf2("第%d次请求开始\n",hit);
|
||||||
|
|
||||||
|
/* 读取请求行和请求头 */
|
||||||
|
rio_readinitb(&rio, fd);
|
||||||
|
rio_readlineb(&rio, buf, MAXLINE);
|
||||||
|
printf3("请求头%d:%s", ++rhn, buf);
|
||||||
|
|
||||||
|
sscanf(buf, "%s %s %s", method, uri, version);
|
||||||
|
if (strcasecmp(method, "GET")) { // 仅支持GET方法
|
||||||
|
error_request(fd, method, "501", "未实现",
|
||||||
|
"本服务器不支持该请求方法");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
read_requesthdrs(&rio,hit,rhn); // 读取剩余请求头
|
||||||
|
|
||||||
|
static_flag = is_static(uri); // 判断资源类型
|
||||||
|
if(static_flag)
|
||||||
|
parse_static_uri(uri, filename); // 解析静态资源路径
|
||||||
|
else
|
||||||
|
parse_dynamic_uri(uri, filename, cgiargs); // 解析动态资源路径和参数
|
||||||
|
|
||||||
|
/* 检查文件是否存在及权限 */
|
||||||
|
if (stat(filename, &sbuf) < 0) {
|
||||||
|
error_request(fd, filename, "404", "未找到",
|
||||||
|
"服务器无法找到该文件");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 根据资源类型发送响应 */
|
||||||
|
if (static_flag) { // 静态资源处理
|
||||||
|
if (!(S_ISREG(sbuf.st_mode)) || !(S_IRUSR & sbuf.st_mode)) {
|
||||||
|
error_request(fd, filename, "403", "禁止访问",
|
||||||
|
"服务器无权读取该文件");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
feed_static(fd, filename, sbuf.st_size); // 发送静态文件内容
|
||||||
|
}
|
||||||
|
else { // 动态资源处理
|
||||||
|
if (!(S_ISREG(sbuf.st_mode)) || !(S_IXUSR & sbuf.st_mode)) {
|
||||||
|
error_request(fd, filename, "403", "禁止访问",
|
||||||
|
"服务器无法执行该CGI程序");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
feed_dynamic(fd, filename, cgiargs); // 执行CGI程序并发送输出
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 判断URI是否对应静态资源 */
|
||||||
|
int is_static(char *uri)
|
||||||
|
{
|
||||||
|
return strstr(uri, "cgi-bin") == NULL; // 不含cgi-bin则为静态资源
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 构造HTTP错误响应 */
|
||||||
|
void error_request(int fd, char *cause, char *errnum,
|
||||||
|
char *shortmsg, char *description)
|
||||||
|
{
|
||||||
|
char buf[MAXLINE], body[MAXBUF];
|
||||||
|
|
||||||
|
/* 构建错误页面内容 */
|
||||||
|
sprintf(body, "<html><title>错误请求</title>");
|
||||||
|
sprintf(body, "%s<body bgcolor=\"#ffffff\">\r\n", body);
|
||||||
|
sprintf(body, "%s<h1>%s %s</h1>\r\n", body, errnum, shortmsg);
|
||||||
|
sprintf(body, "%s<p>%s: %s</p>\r\n", body, description, cause);
|
||||||
|
sprintf(body, "%s<hr><em>weblet Web服务器</em>\r\n", body);
|
||||||
|
|
||||||
|
/* 发送HTTP响应头 */
|
||||||
|
sprintf(buf, "HTTP/1.0 %s %s\r\n", errnum, shortmsg);
|
||||||
|
rio_writen(fd, buf, strlen(buf));
|
||||||
|
sprintf(buf, "Content-type: text/html\r\n");
|
||||||
|
rio_writen(fd, buf, strlen(buf));
|
||||||
|
sprintf(buf, "Content-length: %d\r\n\r\n", (int)strlen(body));
|
||||||
|
rio_writen(fd, buf, strlen(buf));
|
||||||
|
|
||||||
|
/* 发送错误页面内容 */
|
||||||
|
rio_writen(fd, body, strlen(body));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 读取请求头直到空行 */
|
||||||
|
void read_requesthdrs(rio_t *rp,int hit, int rhn)
|
||||||
|
{
|
||||||
|
char buf[MAXLINE];
|
||||||
|
rio_readlineb(rp, buf, MAXLINE);
|
||||||
|
while(strcmp(buf, "\r\n")) {
|
||||||
|
printf3("请求头%d:%s", ++rhn, buf);
|
||||||
|
rio_readlineb(rp, buf, MAXLINE);
|
||||||
|
}
|
||||||
|
printf2("第%d次请求结束\n\n",hit);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 解析静态资源URI到文件路径 */
|
||||||
|
void parse_static_uri(char *uri, char *filename)
|
||||||
|
{
|
||||||
|
strcpy(filename, ".");
|
||||||
|
strcat(filename, uri);
|
||||||
|
if (uri[strlen(uri)-1] == '/')
|
||||||
|
strcat(filename, "index.html"); // 默认返回index.html
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 解析动态资源URI到文件路径和参数 */
|
||||||
|
void parse_dynamic_uri(char *uri, char *filename, char *cgiargs)
|
||||||
|
{
|
||||||
|
char *ptr = index(uri, '?');
|
||||||
|
if (ptr) {
|
||||||
|
strcpy(cgiargs, ptr+1); // 提取参数部分请求头
|
||||||
|
*ptr = '\0'; // 截断URI
|
||||||
|
} else {
|
||||||
|
strcpy(cgiargs, "");
|
||||||
|
}
|
||||||
|
strcpy(filename, ".");
|
||||||
|
strcat(filename, uri);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 发送静态文件内容 */
|
||||||
|
void feed_static(int fd, char *filename, int filesize)
|
||||||
|
{
|
||||||
|
int srcfd;
|
||||||
|
char *srcp, filetype[MAXLINE], buf[MAXBUF];
|
||||||
|
|
||||||
|
/* 发送HTTP响应头 */
|
||||||
|
get_filetype(filename, filetype);
|
||||||
|
sprintf(buf, "HTTP/1.0 200 OK\r\n");
|
||||||
|
sprintf(buf, "%sServer: weblet Web Server\r\n", buf);
|
||||||
|
sprintf(buf, "%sContent-length: %d\r\n", buf, filesize);
|
||||||
|
sprintf(buf, "%sContent-type: %s\r\n\r\n", buf, filetype);
|
||||||
|
rio_writen(fd, buf, strlen(buf));
|
||||||
|
|
||||||
|
/* 发送文件内容 */
|
||||||
|
srcfd = open(filename, O_RDONLY, 0);
|
||||||
|
srcp = mmap(0, filesize, PROT_READ, MAP_PRIVATE, srcfd, 0);
|
||||||
|
close(srcfd);
|
||||||
|
rio_writen(fd, srcp, filesize);
|
||||||
|
munmap(srcp, filesize);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 根据文件扩展名获取MIME类型 */
|
||||||
|
void get_filetype(char *filename, char *filetype)
|
||||||
|
{
|
||||||
|
int i, len;
|
||||||
|
strcpy(filetype, "text/html"); // 默认类型
|
||||||
|
for (i = 0; extensions[i].ext != 0; i++) {
|
||||||
|
len = strlen(extensions[i].ext);
|
||||||
|
if (!strcmp(&filename[strlen(filename)-len], extensions[i].ext)) {
|
||||||
|
strcpy(filetype, extensions[i].filetype);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 启动子进程执行CGI程序 */
|
||||||
|
void feed_dynamic(int fd, char *filename, char *cgiargs)
|
||||||
|
{
|
||||||
|
char buf[MAXLINE], *emptylist[] = { NULL };
|
||||||
|
int pfd[2];
|
||||||
|
|
||||||
|
/* 构造HTTP响应头 */
|
||||||
|
sprintf(buf, "HTTP/1.0 200 OK\r\n");
|
||||||
|
rio_writen(fd, buf, strlen(buf));
|
||||||
|
sprintf(buf, "Server: weblet Web Server\r\n");
|
||||||
|
rio_writen(fd, buf, strlen(buf));
|
||||||
|
|
||||||
|
/* 创建管道并启动子进程 */
|
||||||
|
(void)pipe(pfd);
|
||||||
|
if (fork() == 0) { // 子进程
|
||||||
|
close(pfd[1]); // 关闭写端
|
||||||
|
dup2(pfd[0], STDIN_FILENO); // 重定向标准输入
|
||||||
|
dup2(fd, STDOUT_FILENO); // 重定向标准输出到客户端
|
||||||
|
execve(filename, emptylist, environ); // 执行CGI程序
|
||||||
|
}
|
||||||
|
|
||||||
|
close(pfd[0]); // 父进程关闭读端
|
||||||
|
(void)write(pfd[1], cgiargs, strlen(cgiargs)+1); // 传递参数
|
||||||
|
wait(NULL); // 等待子进程结束
|
||||||
|
close(pfd[1]); // 关闭写端
|
||||||
|
}
|
||||||
19
server-exp2/实验二文件清单.txt
Normal file
19
server-exp2/实验二文件清单.txt
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
common.h : 公共头文件、函数声明、常量定义等(由教材wrapper.h简化而来)
|
||||||
|
common.c : RIO函数库和打开网络连接函数源代码(教材中libwrapper.c简化而来)
|
||||||
|
webclient.c: web客户端源代码(《操作系统实验教程》第1章的client.c)
|
||||||
|
webserver.c: web服务器源代码(即教材《Linux编程》第8章的weblet.c)
|
||||||
|
togglec.c : toggle客户端源代码(教材第8章源代码)
|
||||||
|
togglesi.c : 迭代式toggle服务器源代码(教材《Linux编程》第8章源代码)
|
||||||
|
togglesp.c : 多进程toggle服务器源代码(教材《Linux编程》第9章源代码)
|
||||||
|
togglest.c : 多线程toggle服务器源代码(教材《Linux编程》第9章源代码)
|
||||||
|
togglest_pre.c : 预线程toggle服务器源代码(教材《Linux编程》第9章源代码)
|
||||||
|
togglest_pool.c : 线程池toggle服务器源代码
|
||||||
|
./cgi-bin/add.c: 生成动态网页的cgi程序(教材《Linux编程》第8章)
|
||||||
|
Makefile: 目标和源代码间相互依赖关系文件(参考教材《Linux编程》第3章)
|
||||||
|
index.html: 缺省网页文件
|
||||||
|
example.jpg: 网页文件index.html中内嵌的图片
|
||||||
|
favicon.ico: index.html中内嵌的图标
|
||||||
|
test.html: 第2个测试用网页
|
||||||
|
urls: 记录运行http_load执行时,访问哪些网址
|
||||||
|
|
||||||
|
|
||||||
BIN
web1/bb/ftps
Executable file
BIN
web1/bb/ftps
Executable file
Binary file not shown.
1
web1/bb/hp.txt
Normal file
1
web1/bb/hp.txt
Normal file
@@ -0,0 +1 @@
|
|||||||
|
yeyettttttttttttttttttt
|
||||||
1
web1/bb/ooo.txt
Normal file
1
web1/bb/ooo.txt
Normal file
@@ -0,0 +1 @@
|
|||||||
|
yuuuuutttt
|
||||||
175
web1/bb/perf.txt
Normal file
175
web1/bb/perf.txt
Normal file
@@ -0,0 +1,175 @@
|
|||||||
|
Flat profile:
|
||||||
|
|
||||||
|
Each sample counts as 0.01 seconds.
|
||||||
|
% cumulative self self total
|
||||||
|
time seconds seconds calls us/call us/call name
|
||||||
|
42.86 0.03 0.03 28890 1.04 2.08 process_trans
|
||||||
|
28.57 0.05 0.02 115560 0.17 0.26 rio_readlineb
|
||||||
|
14.29 0.06 0.01 2239020 0.00 0.00 rio_read
|
||||||
|
14.29 0.07 0.01 _init
|
||||||
|
0.00 0.07 0.00 57778 0.00 0.00 rio_writen
|
||||||
|
0.00 0.07 0.00 28890 0.00 0.78 read_requesthdrs
|
||||||
|
0.00 0.07 0.00 28890 0.00 0.00 rio_readinitb
|
||||||
|
0.00 0.07 0.00 28889 0.00 0.00 feed_static
|
||||||
|
0.00 0.07 0.00 28889 0.00 0.00 get_filetype
|
||||||
|
0.00 0.07 0.00 28889 0.00 0.00 is_static
|
||||||
|
0.00 0.07 0.00 28889 0.00 0.00 parse_static_uri
|
||||||
|
0.00 0.07 0.00 1 0.00 0.00 open_listen_sock
|
||||||
|
|
||||||
|
% the percentage of the total running time of the
|
||||||
|
time program used by this function.
|
||||||
|
|
||||||
|
cumulative a running sum of the number of seconds accounted
|
||||||
|
seconds for by this function and those listed above it.
|
||||||
|
|
||||||
|
self the number of seconds accounted for by this
|
||||||
|
seconds function alone. This is the major sort for this
|
||||||
|
listing.
|
||||||
|
|
||||||
|
calls the number of times this function was invoked, if
|
||||||
|
this function is profiled, else blank.
|
||||||
|
|
||||||
|
self the average number of milliseconds spent in this
|
||||||
|
ms/call function per call, if this function is profiled,
|
||||||
|
else blank.
|
||||||
|
|
||||||
|
total the average number of milliseconds spent in this
|
||||||
|
ms/call function and its descendents per call, if this
|
||||||
|
function is profiled, else blank.
|
||||||
|
|
||||||
|
name the name of the function. This is the minor sort
|
||||||
|
for this listing. The index shows the location of
|
||||||
|
the function in the gprof listing. If the index is
|
||||||
|
in parenthesis it shows where it would appear in
|
||||||
|
the gprof listing if it were to be printed.
|
||||||
|
|
||||||
|
Copyright (C) 2012-2026 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
Copying and distribution of this file, with or without modification,
|
||||||
|
are permitted in any medium without royalty provided the copyright
|
||||||
|
notice and this notice are preserved.
|
||||||
|
|
||||||
|
Call graph (explanation follows)
|
||||||
|
|
||||||
|
|
||||||
|
granularity: each sample hit covers 4 byte(s) for 14.29% of 0.07 seconds
|
||||||
|
|
||||||
|
index % time self children called name
|
||||||
|
0.03 0.03 28890/28890 main [2]
|
||||||
|
[1] 85.7 0.03 0.03 28890 process_trans [1]
|
||||||
|
0.00 0.02 28890/28890 read_requesthdrs [4]
|
||||||
|
0.01 0.00 28890/115560 rio_readlineb [3]
|
||||||
|
0.00 0.00 28890/28890 rio_readinitb [8]
|
||||||
|
0.00 0.00 28889/28889 is_static [11]
|
||||||
|
0.00 0.00 28889/28889 parse_static_uri [12]
|
||||||
|
0.00 0.00 28889/28889 feed_static [9]
|
||||||
|
-----------------------------------------------
|
||||||
|
<spontaneous>
|
||||||
|
[2] 85.7 0.00 0.06 main [2]
|
||||||
|
0.03 0.03 28890/28890 process_trans [1]
|
||||||
|
0.00 0.00 1/1 open_listen_sock [13]
|
||||||
|
-----------------------------------------------
|
||||||
|
0.01 0.00 28890/115560 process_trans [1]
|
||||||
|
0.01 0.01 86670/115560 read_requesthdrs [4]
|
||||||
|
[3] 42.9 0.02 0.01 115560 rio_readlineb [3]
|
||||||
|
0.01 0.00 2239020/2239020 rio_read [5]
|
||||||
|
-----------------------------------------------
|
||||||
|
0.00 0.02 28890/28890 process_trans [1]
|
||||||
|
[4] 32.1 0.00 0.02 28890 read_requesthdrs [4]
|
||||||
|
0.01 0.01 86670/115560 rio_readlineb [3]
|
||||||
|
-----------------------------------------------
|
||||||
|
0.01 0.00 2239020/2239020 rio_readlineb [3]
|
||||||
|
[5] 14.3 0.01 0.00 2239020 rio_read [5]
|
||||||
|
-----------------------------------------------
|
||||||
|
<spontaneous>
|
||||||
|
[6] 14.3 0.01 0.00 _init [6]
|
||||||
|
-----------------------------------------------
|
||||||
|
0.00 0.00 57778/57778 feed_static [9]
|
||||||
|
[7] 0.0 0.00 0.00 57778 rio_writen [7]
|
||||||
|
-----------------------------------------------
|
||||||
|
0.00 0.00 28890/28890 process_trans [1]
|
||||||
|
[8] 0.0 0.00 0.00 28890 rio_readinitb [8]
|
||||||
|
-----------------------------------------------
|
||||||
|
0.00 0.00 28889/28889 process_trans [1]
|
||||||
|
[9] 0.0 0.00 0.00 28889 feed_static [9]
|
||||||
|
0.00 0.00 57778/57778 rio_writen [7]
|
||||||
|
0.00 0.00 28889/28889 get_filetype [10]
|
||||||
|
-----------------------------------------------
|
||||||
|
0.00 0.00 28889/28889 feed_static [9]
|
||||||
|
[10] 0.0 0.00 0.00 28889 get_filetype [10]
|
||||||
|
-----------------------------------------------
|
||||||
|
0.00 0.00 28889/28889 process_trans [1]
|
||||||
|
[11] 0.0 0.00 0.00 28889 is_static [11]
|
||||||
|
-----------------------------------------------
|
||||||
|
0.00 0.00 28889/28889 process_trans [1]
|
||||||
|
[12] 0.0 0.00 0.00 28889 parse_static_uri [12]
|
||||||
|
-----------------------------------------------
|
||||||
|
0.00 0.00 1/1 main [2]
|
||||||
|
[13] 0.0 0.00 0.00 1 open_listen_sock [13]
|
||||||
|
-----------------------------------------------
|
||||||
|
|
||||||
|
This table describes the call tree of the program, and was sorted by
|
||||||
|
the total amount of time spent in each function and its children.
|
||||||
|
|
||||||
|
Each entry in this table consists of several lines. The line with the
|
||||||
|
index number at the left hand margin lists the current function.
|
||||||
|
The lines above it list the functions that called this function,
|
||||||
|
and the lines below it list the functions this one called.
|
||||||
|
This line lists:
|
||||||
|
index A unique number given to each element of the table.
|
||||||
|
Index numbers are sorted numerically.
|
||||||
|
The index number is printed next to every function name so
|
||||||
|
it is easier to look up where the function is in the table.
|
||||||
|
|
||||||
|
% time This is the percentage of the `total' time that was spent
|
||||||
|
in this function and its children. Note that due to
|
||||||
|
different viewpoints, functions excluded by options, etc,
|
||||||
|
these numbers will NOT add up to 100%.
|
||||||
|
|
||||||
|
self This is the total amount of time spent in this function.
|
||||||
|
|
||||||
|
children This is the total amount of time propagated into this
|
||||||
|
function by its children.
|
||||||
|
|
||||||
|
called This is the number of times the function was called.
|
||||||
|
If the function called itself recursively, the number
|
||||||
|
only includes non-recursive calls, and is followed by
|
||||||
|
a `+' and the number of recursive calls.
|
||||||
|
|
||||||
|
name The name of the current function. The index number is
|
||||||
|
printed after it. If the function is a member of a
|
||||||
|
cycle, the cycle number is printed between the
|
||||||
|
function's name and the index number.
|
||||||
|
|
||||||
|
|
||||||
|
For the function's parents, the fields have the following meanings:
|
||||||
|
|
||||||
|
self This is the amount of time that was propagated directly
|
||||||
|
from the function into this parent.
|
||||||
|
|
||||||
|
children This is the amount of time that was propagated from
|
||||||
|
the function's children into this parent.
|
||||||
|
|
||||||
|
called This is the number of times this parent called the
|
||||||
|
function `/' the total number of times the function
|
||||||
|
was called. Recursive calls to the function are not
|
||||||
|
included in the number after the `/'.
|
||||||
|
|
||||||
|
name This is the name of the parent. The parent's index
|
||||||
|
number is printed after it. If the parent is a
|
||||||
|
member of a cycle, the cycle number is printed between
|
||||||
|
the name and the index number.
|
||||||
|
|
||||||
|
If the parents of the function cannot be determined, the word
|
||||||
|
`<spontaneous>' is printed in the `name' field, and all the other
|
||||||
|
fields are blank.
|
||||||
|
|
||||||
|
For the function's children, the fields have the following meanings:
|
||||||
|
|
||||||
|
self This is the amount of time that was propagated directly
|
||||||
|
from the child into the function.
|
||||||
|
|
||||||
|
children This is the amount of time that was propagated from the
|
||||||
|
child's children to the function.
|
||||||
|
|
||||||
|
called This is the numbe./perf.txt | ||||||