2017-04-04 65 views
0

我是創建手動套接字的新手。我的操作系統是Ubuntu的。我有使用龍捲風的代理服務器寫巨蟒,一切都很好,當我使用「快速版」啓動應用程序,我的意思是:如何使用套接字啓動應用程序Tornado 4.4

if __name__ == "__main__": 
    app = make_app() 
    port = options.port # default 8000 
    if len(sys.argv) > 1: 
     port = int(sys.argv[1]) 
    app.listen(port) 
    print 'tornado working on port %s' % port 
    tornado.ioloop.IOLoop.current().start() 

但是,當我想改變它使用「插座版本',似乎我做錯了什麼。我收到一條錯誤消息,說該地址已被使用。

代碼:

def make_app(): 
    return MyApplication() 

def connection_ready(sock, fd, events): 
    while True: 
     try: 
      connection, address = sock.accept() 
     except socket.error as e: 
      if e.args[0] not in (errno.EWOULDBLOCK, errno.EAGAIN): 
       raise 
      return 
     connection.setblocking(0) 
     app = make_app() 
     app.listen(8000) # I get here an error: [Errno 98] Address already in use 

if __name__ == "__main__": 
    port = options.port # default port 8000 
    if len(sys.argv) > 1: 
     port = int(sys.argv[1]) 
    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM, 0) 
    sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) 
    sock.setblocking(False) 
    sock.bind(("", port)) 
    sock.listen(128) 
    io_loop = tornado.ioloop.IOLoop.current() 
    callback = functools.partial(connection_ready, sock) 
    io_loop.add_handler(sock.fileno(), callback, io_loop.READ) 
    io_loop.start() 

我想要的文件說(http://www.tornadoweb.org/en/stable/ioloop.html)實現相同的方式,但我沒有看到它開始應用在了那裏。

有人能告訴我什麼是使用套接字啓動應用程序的正確方法?我試圖完成服務器接受傳入套接字時可用的應用程序。 (因此,每個連接到主函數中描述的列表端口的客戶端都將獲得一個新的套接字並可以訪問該應用程序):sock.bind(("", port))sock.listen(128)

編輯:我將我的代理類:

class ProxyHandler(tornado.web.RequestHandler): 

    SUPPORTED_METHODS = ['GET', 'POST'] 

    def data_received(self, chunk): 
     pass 

    def compute_etag(self): 
     return None # disable tornado Etag 

    def handle_response(self, response): 
     if response.error and not isinstance(response.error, tornado.httpclient.HTTPError): 
      self.set_status(500) 
      self.write('Internal server error:\n' + str(response.error)) 
     else: 
      self.set_status(response.code, response.reason) 
      self._headers = tornado.httputil.HTTPHeaders() # clear tornado default header 

      for header, v in response.headers.get_all(): 
       if header not in ('Content-Length', 'Transfer-Encoding', 'Content-Encoding', 'Connection'): 
        self.add_header(header, v) # some header appear multiple times, eg 'Set-Cookie' 

      secured_page = False 
      for page in secure_pages: 
       if page in self.request.uri: 
        secured_page = True 
        self.set_header('Content-Length', len(response.body)) 
        self.write(response.body) 
        break 
      if response.body and not secured_page: 
       c.execute('SELECT filter_name FROM filters WHERE filter_type=1') 
       tags = c.fetchall() 
       soup = BeautifulSoup(response.body, 'html.parser') 
       for row in tags: 
        catched_tags = soup.find_all(str(row[0])) 
        if catched_tags: 
         print 'catched: %s of <%s> tags' % (len(catched_tags), str(row[0])) 
        for tag in catched_tags: 
         tag.extract() 
       new_body = str(soup) 
       self.set_header('Content-Length', len(new_body)) 
       self.write(new_body) 
     self.finish() 

    @tornado.web.asynchronous 
    def get(self): 
     logger.debug('Handle %s request to %s', self.request.method, self.request.uri) 

     body = self.request.body 
     if not body: 
      body = None 

     try: 
      if 'Proxy-Connection' in self.request.headers: 
       del self.request.headers['Proxy-Connection'] 

      c.execute('SELECT filter_name FROM filters WHERE filter_type=2') 
      urls = c.fetchall() 
      for url in urls: 
       if url[0] in self.request.path: 
        self.set_status(403) 
        self.finish() 
        return 

      fetch_request(self.request.uri, self.handle_response, 
         method=self.request.method, body=body, headers=self.request.headers, follow_redirects=False, 
         allow_nonstandard_methods=True) 
     except tornado.httpclient.HTTPError as e: 
      if hasattr(e, 'response') and e.response: 
       self.handle_response(e.response) 
      else: 
       self.set_status(500) 
       self.write('Internal server error:\n' + str(e)) 
       self.finish() 

    @tornado.web.asynchronous 
    def post(self): 
     return self.get() 

而且我對應用程序的URL:

urls = [ 
url(r"/admin/$", mainHandlers.MainHandler), 
url(r"/admin/delete_filter/", mainHandlers.DataDeleteHandler), 
url(r"/admin/filters/$", mainHandlers.DataGetter), 
url(r"/admin/new_filter/$", mainHandlers.FormHandler), 
url(r"/admin/stats/$", mainHandlers.StatsTableHandler), 
url(r"/admin/stats/query/$", mainHandlers.AjaxStatsGetHandler), 
url(r"/static/", StaticFileHandler, dict(path=settings['static_path'])), 
url(r'.*', myProxy.ProxyHandler), 
] 

回答

0

我已經重新將我的代理服務器轉換爲套接字上的純Python代碼,現在我不使用URL,而只處理來自遠程地址的響應。我沒有使用任何框架

0

如果您在Windows上啓動應用程序,你必須等待防火牆疏通。在Windows中,假設應用程序佔用一個端口會被阻塞,以供其他進程使用,這些進程可能會偵聽不適合他們的數據包。

+0

我在ubuntu/linux上運行我的應用程序。我將編輯該問題。 –

1

它說端口已經在使用,因爲它。您在端口8000上監聽至少兩次:當您撥打sock.listen時,在__main__塊中一次,並在撥打app.listen()(它創建另一個套接字並嘗試將其綁定到端口8000)時,再次在connection_ready處理程序中處理。您需要刪除app.listen()一行,但我不明白你想做的事情足以說出你應該做什麼。

+0

感謝您的回覆。我會用這個建議。我正在嘗試創建一個將成爲代理服務器的應用程序。我把代理寫在了處理程序中(我將用代碼更新問題)。我想要做的是在另一端創建一個套接字。我認爲我應該。所以當有兩個套接字時,連接將可用,並且我想通過我的代理服務器發送請求/響應。代理服務器只會過濾一些內容並將過濾後的響應顯示給用戶。 –

+0

我不知道這應該如何工作。我認爲我需要爲每個到服務器的請求創建一個套接字並處理請求。我對嗎? –

+0

我編輯了這個問題,我希望它更清晰一點:) –

相關問題