python实战--Http代理服务器

打算好好深入研究下pytho的socket编程,那天看了这篇博文,http://www.apprk.com/archives/146,于是打算学习下,仿写了一下,发现写好还真不容易,中途出现很多问题,果真是看的容易,做起来难啊。

 源代码如下:

 

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()


我很失望的发现,报了个异常

 

 

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()


结果如下: 

Hello World

lock release

 

 

二.第二个错误就是比较2的了

 

  self.source.send[data]

TypeError: 'builtin_function_or_method' object is unsubscriptable


主要是单词unsubscriptable不认识,呵呵,单词不认识,伤不起啊。

 

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






 

你可能感兴趣的:(python)