代理服务器是在client和server之间的一个服务器,一般起到缓存的作用,所以也叫缓存服务器。比如:
A ----(HTTP)----》 B ----(HTTP)----》 C
其中A是客户端,C是服务器端,那么B就是proxy server了,是代理服务器,也是缓存服务器:当A发起请求时要求获得C上的一个文件,需要先经过B,B在自己的文件系统中寻找是否有A所请求的文件,如果有,就发给A,完成一次响应;如果没有,则在B上创建新的HTTP请求,发送到C,并将C的响应缓存到文件中,同时回发给A。
只要代理服务器B上存在A所需要的文件,就不必劳烦C重新发送响应,一定程度上减轻C的压力,同时减少响应时间。
下面我们用socket编程来实现一个简单的代理服务器,功能为:
访问 localhost:8899/helloworld.html 格式的url时,若helloworld.html与proxy server在同一目录下,那么返回这个文件,否则报错 访问 localhost:8899/www.baidu.com 格式的url时,从proxy server的文件系统中查找www.baidu.com的缓存文件,若存在则返还;若不存在则向baidu.com发起HTTP请求,将得到的响应缓存并发给客户端。其中发送的HTTP请求,由tcp socket实现。
#coding:utf-8from socket import *# 创建socket,绑定到端口,开始监听tcpSerPort = 8899tcpSerSock = socket(AF_INET, SOCK_STREAM)# Prepare a server sockettcpSerSock.bind(('', tcpSerPort))tcpSerSock.listen(5)while True: # 开始从客户端接收请求 print 'Ready to serve...' tcpCliSock, addr = tcpSerSock.accept() print 'Received a connection from: ', addr message = tcpCliSock.recv(4096) # 从请求中解析出filename print message.split()[1] filename = message.split()[1].partition("/")[2] fileExist = "false" filetouse = "/" + filename try: # 检查缓存中是否存在该文件 f = open(filetouse[1:], "r") outputdata = f.readlines() fileExist = "true" print 'File Exists!' # 缓存中存在该文件,把它向客户端发送 tcpCliSock.send("HTTP/1.0 200 OK\r\n\r\n") for i in range(0, len(outputdata)): tcpCliSock.send(outputdata[i]) print 'Read from cache' # 缓存中不存在该文件,异常处理 except IOError: print 'File Exist: ', fileExist if fileExist == "false": # 在代理服务器上创建一个tcp socket print 'Creating socket on proxyserver' c = socket(AF_INET, SOCK_STREAM) hostn = filename.replace("www.", "", 1) print 'Host Name: ', hostn try: # 连接到远程服务器80端口 c.connect((hostn, 80)) print 'Socket connected to port 80 of the host' # 在代理服务器上缓存请求的文件 fileobj = c.makefile('r', 0) #拼凑http get请求的请求行。注意格式为: "请求方法 URI HTTP版本",空格不能省略! fileobj.write("GET " + "http://" + filename + " HTTP/1.0\n\n") # Read the response into buffer buff = fileobj.readlines() # Create a new file in the cache for the requested file. # Also send the response in the buffer to client socket # and the corresponding file in the cache tmpFile = open("./" + filename,"wb") for i in range(0, len(buff)): tmpFile.write(buff[i]) tcpCliSock.send(buff[i]) except: print "Illegal request" else: # HTTP response message for file not found # Do stuff here print 'File Not Found...Stupid Andy' a = 2 # Close the client and the server sockets tcpCliSock.close()# Fill in start.tcpSerSock.close()# Fill in end.
ref:《计算机网络:自顶向下方法》第二章 套接字编程作业4