Python中真正无阻塞的HTTPS服务器 [英] Truly non-blocking HTTPS Server in Python
问题描述
我正在尝试在Python中构建一个真正无阻塞的HTTPS服务器。如果每个人都玩得很好,下面的最小代码就可以了:
I'm trying to build a truly non-blocking HTTPS server in Python. The following minimal code works just fine if everyone is playing nice:
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握手期间阻塞。
However, the problem is that this server blocks at least during the TLS handshake.
测试:
$ nc localhost 4443 # leave this open
然后(在另一个终端):
And then (in another terminal):
$ 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就会继续。这显然不实用。
The wget process blocks, indicating that something is blocked in the server. Once I close the nc process, wget continues. This is obviously not practical at all.
如何在Python中获得真正无阻塞的HTTPS服务器,最好不需要额外的第三方软件?
How do I get a truly non-blocking HTTPS server in Python, preferably without additional third-party software?
我应该提一下,在没有TLS的情况下,相同的代码可以正常工作(即没有wrap_socket行)。
I should mention that the very same code works as expected without TLS (i.e., without the wrap_socket line).
Steffen Ullrich指出如何做到这一点:将 do_handshake_on_connect = False
传递给 wrap_socket
,然后自己做握手。在这种情况下,子类 BaseHTTPServer.HTTPServer
,覆盖 handle
,然后执行握手,如Python文档中所示(套接字称为 self.request
),然后调用super方法。
Steffen Ullrich pointed out how to do it: pass do_handshake_on_connect=False
to wrap_socket
, then do the handshake yourself. In this case, subclass BaseHTTPServer.HTTPServer
, override handle
, and then do the handshake as shown in the Python docs (the socket is called self.request
) followed by calling the super method.
推荐答案
您必须通过使用 do_handshake_on_connect = False
以及稍后调用 ssl.wrap_socket
来执行非阻塞SSL接受自己调用 do_handshake
直到成功为止。请参见 https://docs.python.org/3/library/ssl .html #notes-on-non-blocking-socket .......
You have to do a non-blocking SSL accept by calling ssl.wrap_socket
with do_handshake_on_connect=False
and later calling do_handshake
yourself until it succeeds. See https://docs.python.org/3/library/ssl.html#notes-on-non-blocking-sockets.
你也可以简单地使用 Tornado ,这是一个用python编写的Web服务器,它也完全不阻塞SSL处理。即使您不想自己使用它,您也可以查看源代码以了解如何完成此操作(搜索 do_handshake
)。
You might also simply use Tornado which is a web server written in python and which also does fully non-blocking SSL handling. Even if you don't want to use it yourself you might have a look at the source code to see how this is done (search for do_handshake
).
这篇关于Python中真正无阻塞的HTTPS服务器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!