简体   繁体   English

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

[英]Truly non-blocking HTTPS Server in Python

I'm trying to build a truly non-blocking HTTPS server in Python. 我正在尝试用Python构建一个真正无阻塞的HTTPS服务器。 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()

However, the problem is that this server blocks at least during the TLS handshake. 但是,问题是该服务器至少在TLS握手期间阻塞。

Test with: 测试:

$ 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.

The wget process blocks, indicating that something is blocked in the server. wget进程阻塞,表示服务器中的某些内容被阻止。 Once I close the nc process, wget continues. 一旦我关闭了nc进程,wget就会继续。 This is obviously not practical at all. 这显然不实用。

How do I get a truly non-blocking HTTPS server in Python, preferably without additional third-party software? 如何在Python中获得真正无阻塞的HTTPS服务器,最好不需要额外的第三方软件?

I should mention that the very same code works as expected without TLS (ie, without the wrap_socket line). 我应该提一下,在没有TLS的情况下,相同的代码可以正常工作(即没有wrap_socket行)。


Steffen Ullrich pointed out how to do it: pass do_handshake_on_connect=False to wrap_socket , then do the handshake yourself. Steffen Ullrich指出了如何做到这一点:将do_handshake_on_connect=False传递给wrap_socket ,然后自己进行握手。 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. 在这种情况下,子类BaseHTTPServer.HTTPServer ,覆盖handle ,然后执行握手,如Python文档中所示(套接字称为self.request ),然后调用super方法。

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. 您必须通过使用do_handshake_on_connect=False调用ssl.wrap_socket来执行非阻塞SSL接受, do_handshake自己调用do_handshake直到成功为止。 See https://docs.python.org/3/library/ssl.html#notes-on-non-blocking-sockets . 请参阅https://docs.python.org/3/library/ssl.html#notes-on-non-blocking-sockets

You might also simply use Tornado which is a web server written in python and which also does fully non-blocking SSL handling. 您也可以简单地使用Tornado ,这是一个用python编写的Web服务器,它也可以完全无阻塞地处理SSL。 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 ). 即使您不想自己使用它,您也可以查看源代码以了解如何完成此操作(搜索do_handshake )。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM