HTTP 프록시 서버

高洛峰
高洛峰원래의
2016-10-19 15:24:204368검색

최근에는 파이썬 소켓 프로그래밍을 깊이 있게 공부할 예정이어서 배워서 따라해 보려고 합니다. 그 과정에서 보기는 쉽지만 어려운 일이 많이 발생합니다. 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()

사실 HTTP 프록시 서버 자체는 어렵지 않지만 작성하기가 꽤 번거롭습니다. 여기서는 소스 코드를 자세히 다루지 않겠습니다. 매우 간단합니다. 주로 내가 겪은 문제에 대해 이야기하십시오.

1: 원래는 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()

에 의해 시작된 스레드의 처리되지 않은 예외:

원래 예외:

에 의해 시작된 스레드의 처리되지 않은 예외
오류 sys.Exceptionhook:

원래 예외는 다음과 같습니다.

얼핏 보면 첫 번째 매개변수가 어떻게 객체가 될 수 있는지 말씀드리자면 저는 작성자를 약간 비웃고 경멸했습니다. 그래서 다음날에도 포기하지 않고 코드를 다운받아서 로컬에서 해봤는데 바로 나인 걸 깨닫고 바로 바이두로 갔습니다.

스레드 모듈에서 메인 스레드가 자식 스레드보다 먼저 끝나면 이 예외가 발생하므로 가장 간단한 방법은 메인 스레드가 끝나도록 하는 것입니다. 얼마나 오랫동안 자야할지 모르겠습니다. 어떻게 해결해야 할까요?

더 나은 해결책은 메인 스레드가 각 하위 스레드에 잠금을 추가하고, 하위 스레드가 종료되기 전에 잠금을 해제하고, 메인 스레드가 루프에서 잠금 상태를 계속 확인하는 것입니다. 코드는 다음과 같습니다.

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. 두 번째 오류는 2

self.source.send[data]

peError: 'builtin_function_or_method' 개체를 비교하는 것입니다. unsubscriptable

self.source.send[data]

TypeError: 'builtin_function_or_method' 객체가 unsubscriptable입니다.

주요 의미는 내장 함수나 메서드에 첨자가 있을 수 없다는 것입니다. 알겠습니다


성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.