您的位置:首页 > 理论基础 > 计算机网络

Python入门:python实现http透明代理(二)

2016-08-31 15:33 417 查看
编写此例只是因为个人在学习的过程中遇到了诸多问题,并且没有在网上找到一个比较全面的、浅析的案例,大多案例直接用到了select、queue等等,结构也特别清晰,导致不明白哪些是必要的,业务处理逻辑是什么样,所以在此写出来,作为自己的笔记,同时也可以供初学者参考

浏览器(C)—————-HttpProxy(HP)—————-web服务器(S)

要做http代理,这个代理即要做代理服务端,也要做客户端,要接收两头发来的数据,同时要将两头接收到数据转发至对方

1、C向S发送请求

2、HP拦截(处理)

3、HP处理完拦截的数据转发至S

4、S将返回的数据传递给HP

5、HP再将数据拦截(处理)

6、转交给C

1-6就完成了一次完整的请求

'''
python3.5.2
'''

import socket
import threading
import re

def proxy(ser):                                           #接收线程传递过来的socket对象
conn,addr = ser.accept()                              #接收一个connection然后返回新的connection和address
data = conn.recv(1024)                                #接收从conn收到的数据
#print(data)                                          #查看接收到的内容,收到的数据是byte类型
path_num = data.decode().find('\r\n')                 #解码byte类型数据为字符串,然后查找第一行的末尾数
first_line = data.decode()[:path_num]                 #获取第一行数据(后续要用来判断请求的方法《method》和相对路径)
remain_line = data.decode()[path_num:]                #获取http head及data,即除第一行以外的数据(需要了解http协议就知道为什么这样处理)
method,path_url,protocol = first_line.split()         #http第一行数据中包含三个内容,用空格分割之后就得到三个(后面需要用)
#print(method)                                        #查看method
print(path_url)                                       #查看path_url(即全url)(后续需要用这个url分割相对路径)
#print(protocol)                                      #查看protocol(即http的请求协议,一般就是“http/1.1”)
host = re.findall(r'(?<=://).*?(?=/)',path_url)[0]    #从全url中分割出host(这个host是用来作为proxy转发到web服务器时的目标地址用)
main_url = re.findall(r'.*?://',path_url)[0] + host   #从全url中分割出主url(即http://加host)
#print(main_url)                                      #查看主url
path = path_url[len(main_url):]                       #相对路径/shopxx-mobile/goods/list/243.jhtml
s_data = method + ' ' + path + ' ' + protocol  + remain_line#将抓到的包进行处理,然后合并**作为**后续转发到web服务器的数据
print(s_data)                                         #打印要发送的数据

print(host)                                           #打印host
try:                                                  #判断从抓取到的数据中的host是ip地址类型的,还是域名类型的,然后有不同处理
r_host = socket.gethostbyname(host)               #尝试使用域名解析ip地址,如果解析成功就将port赋值80(这里不严谨,没有考虑https)
port = '80'
except:
if ':' in host:                                   #如果host中有“:”说明host就是ip地址,并分割出ip址和port
r_host,port = host.split(':')
else:
port = '80'
s_s = socket.socket()                                 #再创建一个sockte对象,用于前面分离出的ip与端口进行转发浏览器接收到的数据
print(r_host,port)
s_s.connect((r_host,int(port)))                       #连接从浏览器接收到的数据中的目标ip与端口
print("############################")
print(s_data)                                         #打印要转发的数据
s_s.send(s_data.encode())                             #转发要发送的数据
d = s_s.recv(1024)                                    #接收转发到web服务器的返回数据
print(d)                                              #打印从web服务器返回的数据
conn.send(d)                                          #将接收的数据使用最上面socket对象中的conn进行发送
#ser.close()
#s_s.close()

SER_ADDR = ('', 8088)           #因为socket中的bind需要一个地址与端口的tuple类型
ser = socket.socket()           #创建一个socket对象
ser.bind(SER_ADDR)              #对socket对象绑定地址和端口
ser.listen(5)                   #设置socket对象同时监听多少个链接

while True:                     #为开启线程循环
t = threading.Thread(target=proxy(ser))
t.start()


扩展:

Accept a connection. The socket must be bound to an address and listening for connections. The return value is a pair (conn, address) where conn is a new socket object usable to send and receive data on the connection, and address is the address bound to the socket on the other end of the connection.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  python http代理