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。






 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM