python实战--Http代理服务器

fmwg 10年前

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

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