CSAPP——代理服务器实现(一)

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进行判定

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值