Python中真正无阻塞的HTTPS服务器

时间:2014-10-23 15:02:57

标签: python http ssl

我正在尝试在Python中构建一个真正无阻塞的HTTPS服务器。如果每个人都玩得很好,下面的最小代码就可以了:

import BaseHTTPServer
import SimpleHTTPServer
import SocketServer
import ssl 

class ThreadedHTTPServer(SocketServer.ThreadingMixIn, BaseHTTPServer.HTTPServer):
    pass

httpd = ThreadedHTTPServer(('localhost', 4443), SimpleHTTPServer.SimpleHTTPRequestHandler)
httpd.socket = ssl.wrap_socket(httpd.socket, keyfile="localhost.key", certfile="localhost.pem", server_side=True)
httpd.serve_forever()

但是,问题是此服务器至少在TLS握手期间阻塞。

测试:

$ nc localhost 4443  # leave this open

然后(在另一个终端):

$ wget --no-check-certificate https://localhost:4443/
--2014-10-23 16:55:54--  https://localhost:4443/
Resolving localhost (localhost)... 127.0.0.1
Connecting to localhost (localhost)|127.0.0.1|:4443... connected.

wget进程阻塞,表示服务器中的某些内容被阻止。一旦我关闭了nc进程,wget就会继续。这显然是不切实际的。

如何在Python中获得真正无阻塞的HTTPS服务器,最好不需要额外的第三方软件?

我应该提一下,在没有TLS的情况下,相同的代码按预期工作(即没有wrap_socket行)。


Steffen Ullrich指出如何做到这一点:将do_handshake_on_connect=False传递给wrap_socket,然后自己进行握手。在这种情况下,子类BaseHTTPServer.HTTPServer,覆盖handle,然后执行握手,如Python文档中所示(套接字称为self.request),然后调用super方法。

1 个答案:

答案 0 :(得分:6)

您必须使用ssl.wrap_socket调用do_handshake_on_connect=False并稍后自己调用do_handshake,直到成功为止,才能执行非阻止SSL接受。请参阅https://docs.python.org/3/library/ssl.html#notes-on-non-blocking-sockets

您也可以简单地使用Tornado这是一个用python编写的Web服务器,它也可以完全无阻塞地进行SSL处理。即使您不想自己使用它,也可以查看源代码以了解如何完成此操作(搜索do_handshake)。

相关问题