2

我正在尝试设置一个处理 POST 数据包的 python 服务器。一旦数据包到达,do_POST 会使用 self 和一些数据启动一个新线程,然后,该线程会做一些事情并将接收到的输出放入 self 对象中。这就是我到目前为止所拥有的:

from BaseHTTPServer import BaseHTTPRequestHandler, HTTPServer
....
class httpHandler(BaseHTTPRequestHandler):
    def do_POST(self):
        length = int(self.headers['content-length'])
        data = self.rfile.read(length)
        Resolver(self,data).start()
        return

然后,在我的解析器类中:导入线程

class Resolver(threading.Thread):
    def __init__(self,http,number):
        threading.Thread.__init__(self)
        self.http = http
        self.number = number + "!"

    def run(self):
        self.http.send_response(200)
        self.http.send_header('Content-type','text/html')
        self.http.send_header('Content-length', len(self.number))
        self.http.end_headers()
        # Send the html message
        self.http.wfile.write(self.number)
        return

当然,这只是一个例子而不是完整的表格,我仍处于测试我的程序的阶段。它将在一个弱平台(目前是 Raspberry pi)上运行,我正在寻找一个性能良好的解决方案。有什么建议么 ?

4

2 回答 2

2

问题是BaseHTTPRequestHandler希望您在从do_POST. 这在文档中并不是很清楚,但是如果您查看handle_one_request调用您的方法的方法的源代码,则立即显而易见:

mname = 'do_' + self.command
# ...
method = getattr(self, mname)
mname()
self.wfile.flush() #actually send the response if not already done.

如果您深入研究,您会发现,正如您所期望的那样,代码希望能够在完成处理请求后立即关闭或重用连接。

所以,你不能用BaseHTTPRequestHandler这种方式。

当然,您可以编写自己的处理程序实现。在很大程度上,其中的内容BaseHTTPServer只是作为示例代码,而不是作为一个强大、高效、健壮和灵活的框架(这就是文档直接链接到源代码的原因)。

或者,与其尝试为每个请求创建一个线程,不如为每个连接创建一个线程。ThreadingMixIn类使这很容易。

但是更好的解决方案是使用更好的框架,例如 Twisted 或 Tornado,或者使用一个为您执行线程并仅通过 WSGI 调用您的代码的网络服务器。

于 2013-08-15T21:17:13.120 回答
1

这不是正确的方法。现在,您发送请求的每个线程都将“同时”通过 HTTP 服务器写入响应。您可以添加锁定,但这仍然会基本上破坏目的。

Python 已经提供了一种简单的内置方法来执行此操作。 BaseHTTPServer.HTTPServer是的子类,SocketServer.TCPServer因此您可以使用SocketServer.ThreadingMixIn. Python 文档在这里举了一个例子:

http://docs.python.org/2/library/socketserver.html#asynchronous-mixins

我确信已经存在如何在 SO 上执行此操作的示例。

于 2013-08-15T21:14:22.533 回答