【问题标题】:Threaded BaseHTTPServer, one thread per request线程化 BaseHTTPServer,每个请求一个线程
【发布时间】:2013-10-23 08:52:37
【问题描述】:

我正在尝试使用 BaseHttpServerThreadingMixIn 创建一个多线程 Web 服务器(如在各种示例中所见)。伪代码类似于:

class Handler(BaseHTTPRequestHandler):
    def do_GET(self):
             pass
    def do_POST(self):
             pass

class ThreadedHTTPServer(ThreadingMixIn, HTTPServer):
    """Handle requests in a separate thread."""

if __name__ == '__main__':
    server = ThreadedHTTPServer(('localhost', 9999), Handler)
    print 'Starting server, use <Ctrl-C> to stop'
    server.serve_forever()

这按预期工作,但我的问题是并非每个请求都有一个线程,而是每个 URL 都完成了线程化。我已经这样测试过了:我有一个 URL 绑定来执行以下方法:

import time
import datetime

def request_with_pause(self):
    print datetime.datetime.now().strftime("%H:%M:%S.%f"), 'REQUEST RECEIVED'
    time.sleep(10)
    print datetime.datetime.now().strftime("%H:%M:%S.%f"), 'SENT RESPONSE'

它工作正常,除非我调用 url 两次暂停 5 秒(单击 URL,等待 5 秒,然后再单击一次) - 两个“响应”都在 10 秒后到达(第一次点击的响应)。

【问题讨论】:

  • 这段代码似乎不完整我已经尝试用sleep编写自己的do_GET并且它工作正常
  • 你能把你的do_GET发给我看看吗?
  • 感谢您的帮助。结果我的服务器按预期工作,但客户端给我带来了麻烦。

标签: python multithreading


【解决方案1】:

在 Python 2.7 中:

from BaseHTTPServer import HTTPServer, BaseHTTPRequestHandler
from threading import Thread

class ThreadedHTTPServer(HTTPServer):
    def process_request(self, request, client_address):
        thread = Thread(target=self.__new_request, args=(self.RequestHandlerClass, request, client_address, self))
        thread.start()
    def __new_request(self, handlerClass, request, address, server):
        handlerClass(request, address, server)
        self.shutdown_request(request)

class Handler(BaseHTTPRequestHandler):
    def do_GET(self):
        self.send_response(200)
        self.send_header('Content-type', 'text/html')
        self.end_headers()
        self.wfile.write("hello world")

server = ThreadedHTTPServer(('', 80), Handler)
#server.serve_forever()

HTTPServer类的主要源码可以在SocketServer.py中找到,可以在Python的Lib文件夹中找到目录。 (HTTPServer继承自TCPServerTCPServer继承自BaseServer。)

重要的一行是315:

def process_request(self, request, client_address):
    self.finish_request(request, client_address)
    self.shutdown_request(request)

def finish_request(self, request, client_address):
    self.RequestHandlerClass(request, client_address, self)

此时,服务器使用您的 Handler 类创建新的请求对象。 BaseRequestHandler 构造函数自动调用 self.setup()、self.handle() 和 self.finish() 方法。

所以我所做的是重写 process_request 方法以将这些东西移动到新线程中。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-03-13
    • 2013-02-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多