如何使用套接字启动应用程序Tornado 4.4

时间:2017-04-04 11:30:40

标签: python sockets network-programming tornado

我是创建手动套接字的新手。我的操作系统是ubuntu。我有一个使用Tornado编写python的代理服务器,当我使用启动应用程序的“快速版本”时,一切都很好,我的意思是:

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

我的申请网址:

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),
]

3 个答案:

答案 0 :(得分:1)

它说端口已经在使用,因为它是。你在端口8000上至少听过两次:当你拨打__main__时在sock.listen区块中一次,当你拨打connection_ready时,再次在app.listen()处理程序中另一个套接字并尝试将其绑定到端口8000)。您需要删除app.listen()行,但我不明白您要做的是什么,以说明您应该做什么。

答案 1 :(得分:0)

如果您在Windows上启动应用,则必须等待防火墙取消阻止。在Windows中,可以安全地假设,如果某个应用程序占用一个端口,它将被阻止,以供其他可能侦听不适合它们的数据包的进程使用。

答案 2 :(得分:0)

我已经将我的代理重新连接到套接字上的纯Python代码,我现在没有使用URL,我只处理来自远程地址的响应。我没有使用任何框架