首页 > PHP资讯 > Python培训 > python实战--Http代理服务器

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('n')             if index >0:                 break        #firstLine,self.request=header.split('rn',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 %srn" %(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 socketimport threadimport urlparseimport selectBUFLEN=8192class 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('rn',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 %srn" %(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:                passif __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 threadclass Hello:    def __init__(self,content):        print contentdef 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 threadclass 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培训

本文由欣才IT学院整理发布,未经许可,禁止转载。
支持31不支持0