python实战Http代理服务器

python

最近打算好好深入研究下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("

")

if index >0:

break

#firstLine,self.request=header.split("

",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

" %(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("

")

if index >0:

break

#firstLine,self.request=header.split("

",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

" %(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

主要意思就是说,内置函数或方法无法拥有下标,你懂的



以上是 python实战Http代理服务器 的全部内容, 来源链接: utcz.com/z/524533.html

回到顶部