介绍
该实验中需要实现一个web proxy。Web代理的主要功能是充当客户端和服务器之间的中间人,客户端的请求发送给proxy,proxy把请求转发给服务器,服务器的返回结果也通过proxy转发给客户端。proxy可以对于相同url的请求进行缓存。
准备
原始实验包github下载地址
必要知识《深入理解计算机系统》第二版中的第10章、第11章、第12章内容。
因为本实验包是针对CMU当前用的《CS:APP》第三版的,可能有些函数有些更改。比如
getaddrinfo
函数在第2版中并没有,可以结合原版CSAPP第三版的第11章来了解。
当然这些函数均通过封装,最后我们调用的函数形式与第2版中的相似。
getaddrinfo
能够将传入的用String变量代表的 hostnames、 host addresses、 service names和port number等转换成为socket address structure。它代替了原来的geihostbyname
和getservbyname
。该函数是线程安全的,并且是可重入的函数,而且该函数与协议无关,适用IPV4 IPV6 。
getnameinfo
函数是getaddrinfo
函数的逆函数,功能恰好相反
4.调试./proxy的方法
- telnet
- curl
- netcat
Part 1
实验源码见链接:Part 1 proxy.c
要求:实现一个顺序执行的代理,它可以处理GET方法并转发,对于其他方法可以不实现。
命令行调用./proxy < port >来启动代理服务器,其中port可以通过实验包中的工具port-for-user来获取。
主要流程及函数实现如下:
main函数
中启动服务器端socket,监听接受Port端口客户度HTTP请求,如有连接调用doit函数
进行处理
int main(int argc,char **argv)
{
int listenfd,connfd;
socklen_t clientlen;
char hostname[MAXLINE],port[MAXLINE];
struct sockaddr_storage clientaddr;/*generic sockaddr struct which is 28 Bytes.The same use as sockaddr*/
if(argc != 2){
fprintf(stderr,"usage :%s <port> \n",argv[0]);
exit(1);
}
listenfd = Open_listenfd(argv[1]);
while(1){
clientlen = sizeof(clientaddr);
connfd = Accept(listenfd,(SA *)&clientaddr,&clientlen);
/*print accepted message*/
Getnameinfo((SA*)&clientaddr,clientlen,hostname,MAXLINE,port,MAXLINE,0);
printf("Accepted connection from (%s %s).\n",hostname,port);
/*sequential handle the client transaction*/
doit(connfd);
Close(connfd);
}
return 0;
}