关于Python实现HTTP代理服务器的一些问题。

shizhong_q 2015-06-12 12:48:04
刚刚接触Py,想写一个http代理服务器
最简单的那种 流量转发。
浏览器->Python程序->Web服务器
|
浏览器 -------------- Python程序

但是遇到了一些问题,我自己的程序,开启时候,只能打开一个完整的页面。然后再打开其他页面 就发不出去请求包了。
比如打开 www.csdn.com, 页面 包括 页面的图片、css、js等资源都是可以响应的。再打开其他页面 比如www.sina.com就没反应了(我调试时候py流量全都转发到8080,burpsuit抓包看时候,发现打开第二个页面我的python程序不发送请求)。

下面是我对浏览器请求过程的理解:
1.发送请求,得到响应
2.解析html,请求html里面的一些资源(图片、js、css等)
3.得到资源的响应。渲染。
以上在短连接模式下,每个请求都新建一个socket

我就是依照这个想法写的程序
下面是我程序的流程图:

下面上代码:

# -*- coding:utf-8 -*-
import socket,threading,re,select,urlparse,pdb
lock = threading.Lock()
BUFFER=8192
def HostPort(data):
index = data.find('\n');
firstLine = data[:index-1];
data = data[index+1:];
header={};
header['method'],header['url'],header['protocol'] = firstLine.split();
host = urlparse.urlparse(header['url'])[1];
port = '80';
if ':' in host:
host,port = header['url'].split(':');
port = int(port);
ip = socket.gethostbyname(host);
Request_data = '%s %s %s\r\n%s' % (header['method'],header['url'],header['protocol'],data)
return (Request_data,ip,port);

def New_Link(sock,addr,index):
while True:
data = sock.recv(1024);
lock.acquire();
if(data):
Request_info = HostPort(data);#把浏览器发来的请求处理了下,提取出来端口、并解析域名,修改请求头去除url留下请求的资源
print u'index: %d 请求信息如下:\n%s %s\n%s' % (index,Request_info[1],Request_info[2],Request_info[0]);
else:
break;
lock.release();
s = socket.socket(socket.AF_INET,socket.SOCK_STREAM);
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
#s.connect(('127.0.0.1',8080));调试时候用
s.connect((Request_info[1],Request_info[2]));
s.send(Request_info[0]);
while True:
data=''
(rlist,wlist,elist)=select.select([s],[],[],3)
if rlist:
data=rlist[0].recv(BUFFER)
if len(data)>0:
sock.send(data)
else:
break;

class Client(object):
def __init__(self):
self.Client_Socket = socket.socket(socket.AF_INET,socket.SOCK_STREAM);
self.Client_Socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)#不知道放这里有没有意义
self.Client_Socket.bind(('127.0.0.1',6666));
def Start(self):
self.Client_Socket.listen(5);
print 'Start to listen 6666';
index = 0;#用来标示启动了多少个线程
while True:
s,addr = self.Client_Socket.accept();
index+=1;
t = threading.Thread(target=New_Link,args=(s,addr,index));
t.start();
c = Client();
c.Start();

然后我又在网上下载了一个HTTP代理服务器。发现可以用。我看懂了这个代码,感觉和我写的没啥区别。。。
我也上代码


import socket
import thread
import urlparse
import select

BUFLEN=8192


class Proxy(object):
def __init__(self,conn,addr):
self.source=conn
self.request=""
self.headers={}
self.destnation=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
self.run()

def get_headers(self):
header=''
while True:
header+=self.source.recv(BUFLEN)
index=header.find('\n')
if index >0:
break
#firstLine,self.request=header.split('\r\n',1)
firstLine=header[:index]
self.request=header[index+1:]
self.headers['method'],self.headers['path'],self.headers['protocol']=firstLine.split()

def conn_destnation(self):
url=urlparse.urlparse(self.headers['path'])
hostname=url[1]
port="80"
if hostname.find(':') >0:
addr,port=hostname.split(':')
else:
addr=hostname
port=int(port)
ip=socket.gethostbyname(addr)
print ip,port
self.destnation.connect(('127.0.0.1',8080))
data="%s %s %s\r\n" %(self.headers['method'],self.headers['path'],self.headers['protocol'])
self.destnation.send(data+self.request)
print data+self.request


def renderto(self):
readsocket=[self.destnation]
while True:
data=''
(rlist,wlist,elist)=select.select(readsocket,[],[],3)
if rlist:
data=rlist[0].recv(BUFLEN)
if len(data)>0:
self.source.send(data)
else:
break
#readsocket[0].close();

def run(self):
self.get_headers()
self.conn_destnation()
self.renderto()



class Server(object):

def __init__(self,host,port,handler=Proxy):
self.host=host
self.port=port
self.server=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
self.server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
self.server.bind((host,port))
self.server.listen(5)
self.handler=handler

def start(self):
while True:
try:
conn,addr=self.server.accept()
thread.start_new_thread(self.handler,(conn,addr))
except:
pass


if __name__=='__main__':
s=Server('127.0.0.1',6666)
s.start()

我想知道,我的程序那里错了,另外 网上下这个 和我的程序都有一个通病,开启时候CPU占用很高,尤其是网上下这个。是什么原因?能怎么优化呢?
...全文
4668 5 打赏 收藏 转发到动态 举报
写回复
用AI写文章
5 条回复
切换为时间正序
请发表友善的回复…
发表回复
shizhong_q 2016-06-01
  • 打赏
  • 举报
回复
引用 4 楼 sf_xu 的回复:
楼主你好,我在使用你的代理程序时碰到一些问题,不知道你是否方便帮我解答一下,谢谢
请把问题贴出
sf_xu 2016-05-24
  • 打赏
  • 举报
回复
楼主你好,我在使用你的代理程序时碰到一些问题,不知道你是否方便帮我解答一下,谢谢
shizhong_q 2015-06-16
  • 打赏
  • 举报
回复
引用 2 楼 panghuhu250 的回复:
现在python有context manager:

def New_Link(sock,addr,index):
    while True:
        data = sock.recv(1024)
        with lock:
            if(data):
                Request_info = HostPort(data);#把浏览器发来的请求处理了下,提取出来端口、并解析域名,修改请求头去除url留下请求的资源
                print u'index: %d 请求信息如下:\n%s %s\n%s' % (index,Request_info[1],Request_info[2],Request_info[0]);
            else:
                break
         ...
非常感谢, 我最后是用了 从网上这个的那个版本,经过扩充,写成了满足我要的程序,我写的是一个利用外部api检测sql注入的程序。 唉。同时 想请教一下, 编程里 如果避免这种低级问题?
panghuhu250 2015-06-13
  • 打赏
  • 举报
回复
现在python有context manager:

def New_Link(sock,addr,index):
    while True:
        data = sock.recv(1024)
        with lock:
            if(data):
                Request_info = HostPort(data);#把浏览器发来的请求处理了下,提取出来端口、并解析域名,修改请求头去除url留下请求的资源
                print u'index: %d 请求信息如下:\n%s %s\n%s' % (index,Request_info[1],Request_info[2],Request_info[0]);
            else:
                break
         ...
panghuhu250 2015-06-12
  • 打赏
  • 举报
回复

def New_Link(sock,addr,index):
    while True:
        data = sock.recv(1024);
        lock.acquire();
        if(data):
            Request_info = HostPort(data);#把浏览器发来的请求处理了下,提取出来端口、并解析域名,修改请求头去除url留下请求的资源
            print u'index: %d 请求信息如下:\n%s %s\n%s' % (index,Request_info[1],Request_info[2],Request_info[0]);
        else:
            # 加上lock.release()
            break; # 从这儿跳出while后, lock还没有release.
        lock.release();
        ...
看上面break处的注释

37,721

社区成员

发帖
与我相关
我的任务
社区描述
JavaScript,VBScript,AngleScript,ActionScript,Shell,Perl,Ruby,Lua,Tcl,Scala,MaxScript 等脚本语言交流。
社区管理员
  • 脚本语言(Perl/Python)社区
  • IT.BOB
加入社区
  • 近7日
  • 近30日
  • 至今

试试用AI创作助手写篇文章吧