proxy.docx
《proxy.docx》由会员分享,可在线阅读,更多相关《proxy.docx(14页珍藏版)》请在冰豆网上搜索。
proxy
#define_GNU_SOURCE
#include
#include
#include
#include
#include"csapp.h"
#defineDEBUG
#ifdefDEBUG
#definedbg_printf(...)printf(__VA_ARGS__)
#else
#definedbg_printf(...)
#endif
#defineDEBUG_CACHE
#ifdefDEBUG_CACHE
#definedbgC_printf(...)printf(__VA_ARGS__)
#else
#definedbgC_printf(...)
#endif
#defineMAX_CACHE_SIZE1048576
#defineMAX_OBJECT_SIZE102400
/*----------------------------------------*/
/*structure*/
typedefstruct{
intserverPort;
charmethod[MAXLINE],url[MAXLINE];
charversion[MAXLINE],hostname[MAXLINE],path[MAXLINE];
}requestHeader;
structcacheSet{
charhostname[MAXLINE];//hostname
charpath[MAXLINE];//path
structcacheSet*next;//pointertonextcacheset
char*buffer;//bufferpointer
inttime;//timestamp
intlen;//buffersize
};
/*-----------*/
void*doit(void*);
structcacheSet*cacheSearch(char*hostname,char*path);
structcacheSet*cacheFindLRU(intlen);
intcacheAdd(char*hostname,char*path,char*buf,intlen);
intglobalTime=0;
structcacheSet*cache;
sem_tmutex_time;
intreadcnt=0;
sem_tmutex,w;
sem_tmutexHostName;
/*-----------------*/
intmain(intargc,char*argv[])
{
intfd;
if((fd=open("output.txt",O_RDWR,0))>0)
dup2(fd,1);
pthread_ttid;
structsockaddr_inclientaddr;
intlistenfd;
int*connfdp;
intport;
socklen_tclientLen=sizeof(structsockaddr_in);
//initilizecache
cache=malloc(sizeof(structcacheSet));
if(cache==NULL){
fprintf(stderr,"failtomalloccache.\n");
exit
(1);
}
strcpy(cache->hostname,"");
strcpy(cache->path,"");
cache->next=NULL;
cache->buffer=NULL;
cache->time=0;
cache->len=0;
//initilizesemaphore
sem_init(&mutex_time,0,1);
sem_init(&mutex,0,1);
sem_init(&w,0,1);
sem_init(&mutexHostName,0,1);
/*examtheportnumber*/
if(argc!
=2){
fprintf(stderr,"Noportnumber!
\n");
exit
(1);
}
/*ignoretheSIGPIPE*/
Signal(SIGPIPE,SIG_IGN);
port=atoi(argv[1]);
if((listenfd=open_listenfd(port))<0){
fprintf(stderr,"failtoopenlistenfd!
\n");
exit(-1);
}
/*createanewthread*/
while
(1){
if((connfdp=(int*)malloc(sizeof(int)))==NULL){
fprintf(stderr,"failtogetspacefromheap!
!
\n");
continue;
}
if((*connfdp=accept(listenfd,(SA*)&clientaddr,&clientLen))<0){
fprintf(stderr,"failtoacceptaconnfdprequest!
\n");
continue;
}
if((pthread_create(&tid,NULL,doit,connfdp))!
=0){
fprintf(stderr,"failtocreateathread!
!
\n");
continue;
}
}
return0;
}
/*
*parsetheheader
*/
intparse_uri(requestHeader*header,rio_t*clientRio)
{
char*ptr;
inti=0,j=0;
intlength;
charport[MAXLINE]="80";
if(!
strncasecmp(header->url,"http:
//",7)){
/*surpass"http:
//"*/
char*first=header->url+7;
char*as=header->url;
while(*first)
{
*as=*first;
as++;
first++;
}
*as='\0';
/*whetherpathistherootdirectory*/
if(!
(ptr=strchr(header->url,'/')))
strcpy(header->path,"/");
/*getthepath*/
else{
strcpy(header->path,ptr);
}
/*getthehostname*/
length=strlen(header->url);
for(i=0;iif(header->url[i]=='/')
break;
if(header->url[i]==':
')
break;
header->hostname[i]=header->url[i];
}
header->hostname[i]='\0';
/*getportnumber*/
if(header->url[i]==':
'){
i++;
length=strlen(header->url+i);
for(j=0;length;j++,i++){
if(header->url[i]=='/')
break;
port[j]=header->url[i];
}
port[j]='\0';
}
}
header->serverPort=atoi(port);
return0;
}
/*
*servethesingleclient
*/
void*doit(void*vargp)
{
rio_tclientRio,serverRio;
intconnfd=*(int*)vargp;
pthread_ttid;
intlength;
charbuf[MAXLINE],recBuf[MAX_OBJECT_SIZE];
requestHeaderheader;
intconnfd2server;
structcacheSet*set;
intlenSum=0;
free(vargp);
tid=pthread_self();
if((pthread_detach(tid))!
=0){
fprintf(stderr,"failtodetachthread:
%d\n",(int)tid);
close(connfd);
pthread_exit(NULL);
}
/*readthefirstlineofheaderintherequest*/
rio_readinitb(&clientRio,connfd);
if(rio_readlineb(&clientRio,buf,MAXLINE)<0){
fprintf(stderr,"failtoreadthefirstlinefromtherequest!
\n");
close(connfd);
pthread_exit(NULL);
}
dbg_printf("buf=%s\n",buf);
sscanf(buf,"%s%s%s",header.method,header.url,header.version);
dbg_printf("method=%s,url=%s,version=%s\n",header.method,header.url,header.version);
/*onlysurpportGETmethod*/
if(strcmp(header.method,"GET")){
fprintf(stderr,"wecannotforward%smethod!
!
\n",header.method);
close(connfd);
pthread_exit(NULL);
}
if(parse_uri(&header,&clientRio)<0){
fprintf(stderr,"failtoparsetheheader)!
\n");
close(connfd);
pthread_exit(NULL);
}
dbg_printf("serverPort=%d,hostname=%s\n",header.serverPort,header.hostnam