python實戰--Http代理服務器
最近打算好好深入研究下python的socket編程, 于是打算學習下,仿寫了一下,發現寫好還真不容易,中途出現很多問題,果真是看的容易,做起來難啊
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((ip,port))
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
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',8080)
s.start()
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((ip,port))
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
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',8080)
s.start() 其實Http代理服務器本身不難,但寫出來還是挺費事的,這里就不細說源代碼了,很簡單。主要說說,我遇到的問題。
一: 我本來只知道,thread.start_new_thread的第一個參數是函數對象,但當我看到上面的博文時,心里一愣,這樣也可以,于是我迅速的測試了一下:
import thread
class Hello:
def __init__(self,content):
print content
def cs():
thread.start_new_thread(Hello, ("Hello World",))
if __name__=='__main__':
cs()
import thread
class Hello:
def __init__(self,content):
print content
def cs():
thread.start_new_thread(Hello, ("Hello World",))
if __name__=='__main__':
cs() Unhandled exception in thread started by
Error in sys.excepthook:
Original exception was:
Unhandled exception in thread started by
Error in sys.excepthook:
Original exception was:
一看,我說嘛,第一個參數怎么可以是對象,我呵呵一笑,稍微鄙視了一下作者。于是,我洗洗睡了,第二天,我還是不死心,于是把代碼下下來,本地實驗了一下,可以的,立馬意識到是我2了,于是立馬百度。
原來thread模塊中,主線程如果比子線程先結束,就會拋出這個異常,所以我們必須讓子線程先結束,最簡單的方法就是讓主線程sleep足夠長的時間,至于多長時間,貌似不知道,那到底怎么解決呢?
比較好的解決辦法就是,主線程給每個子線程都加一把鎖,子線程在結束前將鎖釋放掉,主線程一直循環檢查鎖的狀態。代碼如下:
import thread
class Hello:
def __init__(self,content,lock):
print content
"""
do something
....
At the end,release the lock
"""
lock.release()
def cs():
lock=thread.allocate_lock()
lock.acquire()
thread.start_new_thread(Hello, ("Hello World",lock))
while True:
if not lock.locked():
break
print "lock release"
if __name__=='__main__':
cs()
import thread
class Hello:
def __init__(self,content,lock):
print content
"""
do something
....
At the end,release the lock
"""
lock.release()
def cs():
lock=thread.allocate_lock()
lock.acquire()
thread.start_new_thread(Hello, ("Hello World",lock))
while True:
if not lock.locked():
break
print "lock release"
if __name__=='__main__':
cs() 二.第二個錯誤就是比較2的了
self.source.send[data]
peError: 'builtin_function_or_method' object is unsubscriptable
self.source.send[data]
TypeError: 'builtin_function_or_method' object is unsubscriptable
主要意思就是說,內置函數或方法無法擁有下標,你懂的