ホームページ  >  記事  >  バックエンド開発  >  HTTPプロキシサーバー

HTTPプロキシサーバー

高洛峰
高洛峰オリジナル
2016-10-19 15:24:204318ブラウズ

最近、Pythonソケットプログラミングを深く勉強する予定なので、それを学んで真似するつもりですが、途中で多くの問題が表示され、見るのは簡単ですが、難しいことがわかりました。 do

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

実際、プロキシサーバー自体は難しくありませんが、非常に簡単なので、ここではソースコードを詳しく説明しません。主に私が遭遇した問題について話します。

1: 元々、thread.start_new_thread の最初のパラメータが関数オブジェクトであることしか知らなかったのですが、上記のブログ投稿を見てびっくりしたので、すぐにテストしてみました。スレッドは

sys.Excepthook のエラーによって開始されました:


元の例外は:

パラメータがオブジェクトである可能性はありますか? 私は笑って、作者を少し軽蔑しました。それで、翌日、私はまだ諦めていなかったので、コードをダウンロードしてローカルで試してみましたが、すぐにそれが私であることに気づき、すぐにBaiduに行きました。

スレッド モジュールでは、メイン スレッドが子スレッドより先に終了すると、この例外がスローされることが判明したため、子スレッドを最初に終了させる必要があります。最も簡単な方法は、メイン スレッドを長時間スリープさせることです。どれくらい時間がかかるかわからないようですが、どうすれば解決できますか?

より良い解決策は、メインスレッドが各サブスレッドにロックを追加し、サブスレッドが終了する前にロックを解放し、メインスレッドがループ内でロックのステータスをチェックし続けることです。コードは次のとおりです:

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

2. 2 番目のエラーは 2 を比較しています

self.source.send[data]

peError: 'builtin_function_or_method' object is unsubscriptable

self.source.send[data]

TypeError : 'builtin_function_or_method' オブジェクトは添字が付けられません

主な意味は、組み込み関数またはメソッドには添字を付けることができないということです

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。