proxyserver lab的实现
根据csapp的要求,要求实现以下三个功能
1、基本的传输
2、多线程
3、缓存
1、基本传输
基本传输分为四步
1、代理服务器接收客户端的数据
2、代理服务器把接收到的数据传给目标服务器
3、接收目标服务器发送来的数据
4、代理服务器把接收到的数据传给客户端
首先我们需要监听端口,用Open_listenfd函数来进行监听,随后生成多线程和处理函数doit(这里我用P、V操作,限制住了多线程)
int main(int argc, char **argv)
{
int listenfd, *connfdp;
socklen_t clientlen;
struct sockaddr_storage clientaddr;
pthread_t tid;
printf("代理服务器正在启动....\n");
if(argc!=2)
{
printf("没有端口号\n");
exit(1);
}
Sem_init(&mutex, 0, 1);
init_cache();
//监听客户端
printf("正在监听端口...\n");
listenfd = Open_listenfd(argv[1]);
while(1)
{
P(&mutex);
clientlen=sizeof(struct sockaddr_storage);
connfdp=Malloc(sizeof(int));
*connfdp=Accept(listenfd,(SA *)&clientaddr, &clientlen);
Pthread_create(&tid, NULL, thread, connfdp);
V(&mutex);
}
}
void *thread(void *vargp)
{
printf("进入线程\n");
int connfd = *((int *)vargp);
Pthread_detach(pthread_self());
Free(vargp);
doit(connfd);
Close(connfd);
return NULL;
}
接下来就是doit处理函数了,首先说明一下,由于未理解题意,我把缓存当成了,存储目标服务器数据的缓存,方便相同的客户端再次访问时,不需要连接目标服务器了。
void doit(int clientfd)
{
printf("进入处理函数\n");
char buf[MAXLINE], method[MAXLINE], uri[MAXLINE], version[MAXLINE];
// char filename[MAXLINE], cgiargs[MAXLINE];
//接受客户端的信息
printf("正在接受客户端信息...\n");
rio_t rio;
int len = recv(clientfd, buf, MAXLINE, NULL);
if(len<0)
{
printf("接受客户端的数据失败\n");
return ;
}
sscanf(buf,"%s %s %s\n",method, uri, version);
//printf("--------------%s %s %s\n", method, uri, version);
struct cache_HttpHeader cache_head;
int index=-1;
printf("判断是否在缓存中\n");
parseHead(buf,&cache_head);
index=is_exist(cache_head);
if(index!=-1)
{
printf("缓存中存在该服务器的访问记录\n");
//在缓存中,找到对应的服务器发送来的信息
int tmp=0;
printf("----------%d %d-------------\n",index, cache[index].object_size);
while(tmp<cache[index].object_size)
{
printf("正在通过缓存发送数据...\n");
printf("---------查看从缓存中发送来的数据---------\n");
printf("%s\n",cache[index].buffer+tmp);
Rio_writen(clientfd,cache[index].buffer+tmp, MAXLINE);
tmp+=MAXLINE;
}
if(tmp<cache[index].object_size)Rio_writen(clientfd, cache[index].buffer+tmp,cache[index].object_size-tmp);
//更新时间
printf("正在更改最近一次访问时间...\n");
time(&cache[index].date);
return;
}
//未在缓存中
int serverfd;
char hosthome[MAXLINE]="127.0.0.1", port[MAXLINE]="3000";
//P(&mutex);
printf("正在连接目标服务器...\n");
if((serverfd = Open_clientfd(hosthome, port))<0)
{
printf("目标服务器连接失败\n");
Close(serverfd);
return ;
}
//V(&mutex);
//发送客户端的信息给目标服务器
printf("连接成功!\n正在给目标服务器发送信息\n");
if(send(serverfd, buf, MAXLINE, NULL)<0)
{
printf("发送信息失败\n");
return ;
}
//接收目标服务器的信息
printf("正在接收目标服务器信息...\n");
Rio_readinitb(&rio, serverfd);
cache[cache_index].buffer=(char *)malloc(sizeof(char)*MAX_OBJECT_SIZE);
int len2;
while((len2=rio_readnb(&rio,buf,MAXLINE))>0)
{
//写回客户端
printf("正在把数据写回客户端...\n");
Rio_writen(clientfd, buf, len2);
printf("以下是目标服务器传给客户端的原始数据:\n");
/*for(int i=0;i<len2;i++)
{
printf("%c\n",buf[i]);
}*/
printf("把访问数据放入缓存中\n");
addbuffer(buf,cache[cache_index].object_size, len2);
cache[cache_index].object_size+=len2;
memset(buf, 0, len2);
}
/*
for(int i=0;i<cache[cache_index].object_size;i++)
printf("%c\n",cache[cache_index].buffer[i]);
*/
addHead(cache_head,cache[cache_index].object_size);
Close(serverfd);
return;
}
目前这个程序存在以下五个问题:
1、缓存的内存分配是静态的,不是动态的
2、未实现多线程,目前还是单线程
3、未实现读写模式的P、V操作
4、未进行cache[].buffer的溢出处理
5、未对host进行判定