SimpleHTTPRequestHandler在do_POST方法返回前关闭连接
我正在用Python写一个简单的网页服务器。下面是我代码的简化版本:
class StreamerHandler(SimpleHTTPRequestHandler):
def do_POST(self):
try:
length = int(self.headers.getheader('content-length'))
data = self.rfile.read(length)
self.send_response(200, "OK")
#process_data(data, self.client_address)
except Exception as inst:
logging.error(type(self).__name__ + "/" + type(inst).__name__ + " (" + inst.__str__() + ")")
class Streamer(TCPServer):
def __init__(self, overlay):
self.allow_reuse_address = True
TCPServer.__init__(self, ("", port), StreamerHandler)
我想做的是先发送响应,然后关闭TCP连接,接着再运行一个叫process_data的方法,这个方法可能需要很长时间才能完成。
有没有办法做到这一点?我能想到的唯一解决方案就是用一个专门的线程来处理这个过程。
2 个回答
3
首先,SimpleHTTPRequestHandler
是从 BaseHTTPServer.BaseHTTPRequestHandler
这个类继承而来的,而 BaseHTTPRequestHandler
又是从 SocketServer.StreamRequestHandler
这个类继承的。
在 SocketServer.StreamRequestHandler
里,rfile
和 wfile
这两个伪文件是在 setup()
方法中通过一个叫 self.connection
的套接字对象创建的:
def setup(self):
self.connection = self.request
if self.timeout is not None:
self.connection.settimeout(self.timeout)
if self.disable_nagle_algorithm:
self.connection.setsockopt(socket.IPPROTO_TCP,
socket.TCP_NODELAY, True)
self.rfile = self.connection.makefile('rb', self.rbufsize)
self.wfile = self.connection.makefile('wb', self.wbufsize)
这个套接字 self.connection
仍然可以使用,所以你可以调用 self.connection.close()
来关闭它。不过,wfile
这个伪文件里面可能有一些缓存的数据,如果直接关闭可能会丢失这些数据。因此,你应该调用 self.finish()
,这个方法也是在 SocketServer.StreamRequestHandler
中定义的:
def finish(self):
if not self.wfile.closed:
self.wfile.flush()
self.wfile.close()
self.rfile.close()
所以,我觉得下面的代码应该可以工作(虽然还没测试过):
class StreamerHandler(SimpleHTTPRequestHandler):
def do_POST(self):
try:
length = int(self.headers.getheader('content-length'))
data = self.rfile.read(length)
self.send_response(200, "OK")
self.finish()
process_data(data, self.client_address)
except Exception as exc:
logging.error(
"{0}/{1}({2})".format(
type(self).__name__, type(exc).__name__, str(exc)))
7
我试了一下,实际上你需要按顺序执行这两个命令才能关闭它:
self.finish()
self.connection.close()