代理服务器是在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-8
from socket import * # 创建socket,绑定到端口,开始监听
tcpSerPort = 8899
tcpSerSock = socket(AF_INET, SOCK_STREAM) # Prepare a server socket
tcpSerSock.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

最新文章

  1. using namespace std 和 using std::cin
  2. lattice 与 modelsim 仿真 笔记
  3. MyBatis入门学习(二)
  4. PHP-FPM-failed to ptrace(PEEKDATA) pid 123: Input/output error
  5. Linux服务器上监控网络带宽的18个常用命令(转)
  6. poj 3469
  7. Highcharts教程2
  8. Delphi 内存分配 StrAlloc New(转)
  9. T-SQL编程语句
  10. delphi JPG图片 旋转 切边 缩放
  11. Java中Semaphore(信号量)的使用
  12. html5闰年判断函数
  13. 论Ubuntu下的docker多难搭建
  14. centos 安装 Vagrant
  15. Vue的生命周期的介绍
  16. 8-13 Just Finish it up uva11093
  17. 【文智背后的奥秘】系列篇——基于CRF的人名识别
  18. [USACO08JAN]Telephone Lines
  19. POJ3709_K-Anonymous Sequence
  20. PentesterLab-From SQL Injection to Shell: PostgreSQL edition

热门文章

  1. bzoj3306: 树(dfs序+倍增+线段树)
  2. PID控制算法的C语言实现五 积分分离的PID控制算法C语言实现
  3. The 14th Zhejiang Provincial Collegiate Programming Contest Sponsored by TuSimple - F 贪心+二分
  4. bzoj 4332: JSOI2012 分零食 快速傅立叶变换
  5. discuz开发,登录次数过多,锁定解决方法
  6. LightOJ 1244 - Tiles 猜递推+矩阵快速幂
  7. JavaScrip入门笔记(二)
  8. C/C++程序员必备的15个编辑器和集成开发环境
  9. 2016-2017-2 20155117实验二《Java面向对象程序设计》实验报告
  10. DOM基础操作