最後兩章的內容還蠻多的,並且代碼很密,須要去讀才能作proxylabapp
proxylab作的很惱火,由於須要去調,我最後沒作完,由於報頭信息懶得弄了,part 3 cach的部分也沒作。。。測試
下面這段是通不過測試的,由於只能響應特定類型的請求格式,或者說可以響應的請求類型比lab要求的還少。。。之後有時間再作吧。。。(並不會)this
1 #include <stdio.h> 2 #include "csapp.h" 3 #include <pthread.h> 4 5 6 /* Recommended max cache and object sizes */ 7 #define MAX_CACHE_SIZE 1049000 8 #define MAX_OBJECT_SIZE 102400 9 10 void doit(int fd); 11 int parse_uri(char *uri, char *hostname, char *filename, char *port); 12 void *thread(void *vargp); 13 14 /* You won't lose style points for including this long line in your code */ 15 static const char *user_agent_hdr = "User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:10.0.3) Gecko/20120305 Firefox/10.0.3\r\n"; 16 17 int main(int argc, char **argv) 18 { int listenfd, connfd; 19 char hostname[MAXLINE], port[MAXLINE]; 20 socklen_t clientlen; 21 struct sockaddr_storage clientaddr; 22 pthread_t tid; 23 24 /* Check command line args */ 25 if (argc != 2) { 26 fprintf(stderr, "usage: %s <port>\n", argv[0]); 27 exit(1); 28 } 29 30 listenfd = Open_listenfd(argv[1]); 31 while (1) { 32 clientlen = sizeof(clientaddr); 33 connfd = Accept(listenfd, (SA *)&clientaddr, &clientlen); 34 Getnameinfo((SA *) &clientaddr, clientlen, hostname, MAXLINE, 35 port, MAXLINE, 0); 36 printf("Accepted connection from (%s, %s)\n", hostname, port); 37 Pthread_create(&tid, NULL, thread, (void *)connfd); 38 //doit(connfd); 39 //Close(connfd); 40 printf("%s disconnected\n", hostname); 41 } 42 43 //printf("%s", user_agent_hdr); 44 return 0; 45 } 46 47 void doit(int fd) 48 { 49 char buf[MAXLINE], method[MAXLINE], uri[MAXLINE], version[MAXLINE]; 50 char newhead[MAXLINE],result[MAXLINE]; 51 rio_t rio, rio_2; 52 int clientfd; 53 char port[MAXLINE]; 54 int n=0,flag=0; 55 char hostname[MAXLINE],filename[MAXLINE]; 56 57 58 Rio_readinitb(&rio, fd); 59 Rio_readlineb(&rio, buf, MAXLINE); 60 61 printf("%s", buf); 62 sscanf(buf, "%s %s %s", method, uri, version); 63 if (strcasecmp(method, "GET")) { 64 sprintf(newhead,"%s: proxy does not implement this method\n", method); 65 Rio_writen(fd, newhead, strlen(newhead)); 66 return; 67 } 68 if ( strcasecmp(version, "HTTP/1.0") && strcasecmp(version, "HTTP/1.0")) { 69 sprintf(newhead,"%s: proxy does not support this version\n", version); 70 Rio_writen(fd, newhead, strlen(newhead)); 71 return; 72 } 73 74 flag = parse_uri(uri, hostname, filename, port); 75 if (!flag){ 76 sprintf(newhead,"something is wrong"); 77 Rio_writen(fd, newhead, strlen(newhead)); 78 return; 79 } 80 81 clientfd = Open_clientfd(hostname, port); 82 Rio_readinitb(&rio_2, clientfd); 83 84 sprintf(newhead,"GET /%s HTTP/1.0\r\n", filename); 85 sprintf(newhead,"%sHost: %s\r\n",newhead, hostname); 86 sprintf(newhead,"%s%s",newhead, user_agent_hdr); 87 sprintf(newhead,"%sConnection: close\r\n", newhead); 88 sprintf(newhead,"%sProxy-Connection: close\r\n\r\n", newhead); 89 90 Fputs(newhead, stdout); 91 92 Rio_writen(clientfd, newhead, strlen(newhead)); 93 94 while ((n = Rio_readlineb(&rio_2, result, MAXLINE))!= 0) { 95 Rio_readlineb(&rio_2, result, MAXLINE); 96 //Fputs(result, stdout); 97 Rio_writen(fd, result, strlen(result)); 98 } 99 100 } 101 102 int parse_uri(char *uri, char *hostname, char *filename, char *port) 103 { 104 105 char *ptr, *ptr2; 106 107 strcpy(port , "80"); 108 109 ptr = strstr(uri, "//"); 110 111 if(!ptr) 112 ptr = uri; 113 else 114 ptr = ptr + 2; 115 116 ptr2 = strstr(ptr, ":"); 117 118 if(ptr2){ 119 *ptr2 = '\0'; 120 sscanf(ptr,"%s",hostname); 121 sscanf(ptr2+1,"%d%s", (int *)port, filename); 122 } 123 else{ 124 ptr2 = strstr(ptr, "/"); 125 126 if(!ptr2){ 127 strcpy(hostname, ptr); 128 filename = NULL; 129 } 130 else { 131 strcpy(filename, ptr2+1); 132 *ptr = '\0'; 133 strcpy(hostname, ptr); 134 } 135 } 136 137 return 1; 138 } 139 140 void *thread(void *vargp) 141 { 142 int connfd = (int) vargp; 143 Pthread_detach(pthread_self()); 144 doit(connfd); 145 Close(connfd); 146 return NULL; 147 }