from twisted.web.resource import Resource
from twisted.web.server import Site, Session
from twisted.internet import ssl
from twisted.internet import reactor
class Echo(Resource):
def render_GET(self, request):
return "GET"
class WebSite(Resource):
def start(self):
factory = Site(self, timeout=5)
factory.sessionFactory = Session
self.putChild("echo", Echo())
reactor.listenSSL(443, factory, ssl.DefaultOpenSSLContextFactory('privkey.pem', 'cacert.pem'))
#reactor.listenTCP(8080, factory)
self.sessions = factory.sessions
if __name__ == '__main__':
ws = WebSite()
ws.start()
reactor.run()
在上面的代码中,当我从网络浏览器输入 url“https://localhost/echo”时,它会获取页面。 5 秒后我尝试重新加载页面,它不刷新网页,卡在重新加载操作上。在第二次尝试重新加载时,它会立即获取页面。
当我使用 reactor.listenTCP(8080, factory) 运行上面的代码时,没有出现这样的问题。 (我可以重新加载页面而无需卡住重新加载并立即获取页面)
问题可能会在 Chrome、Firefox 中重复出现。但是当我用 Ubuntu 的 Epiphany 浏览器尝试时,没有出现这样的问题。
我不明白为什么会这样。
任何关于理解/解决问题的评论都将被采纳。
额外信息:
- 当我使用 listenSSL 时,与连接相关的文件描述符不会在超时秒后关闭。重新加载页面时它保持静止,在第二次重新加载操作时,它关闭并打开新的文件描述符。 (我立即获得页面)
- 当我使用 listenTCP 时,文件描述符会在超时秒后关闭,当我重新加载页面时,它会打开新的文件描述符并立即返回页面。
- 还有 Telnet 连接,在这两种情况下它都会按预期超时连接。
- 连接此服务器的 Twisted 客户端也会按预期影响超时。
最佳答案
超时连接的类是TimeoutMixin类。
它使用 transport.loseConneciton() 方法使连接超时。
不知何故,DefaultOpenSSLFactory 使用连接(?),因此 loseConnection 方法等待完成传输,此时它不接受连接上的任何进程。
根据扭曲的文档:
In the code above, loseConnection is called immediately after writing to the transport. The loseConnection call will close the connection only when all the data has been written by Twisted out to the operating system, so it is safe to use in this case without worrying about transport writes being lost. If a producer is being used with the transport, loseConnection will only close the connection once the producer is unregistered.
In some cases, waiting until all the data is written out is not what we want. Due to network failures, or bugs or maliciousness in the other side of the connection, data written to the transport may not be deliverable, and so even though loseConnection was called the connection will not be lost. In these cases, abortConnection can be used: it closes the connection immediately, regardless of buffered data that is still unwritten in the transport, or producers that are still registered. Note that abortConnection is only available in Twisted 11.1 and newer.
因此,当我通过覆盖它在 timeoutMixinClass 上将 loseConnection() 更改为 abortConnection() 时,情况不再发生。
当我阐明为什么 loseConnection 在特定情况下不足以关闭连接的原因时,我会在这里注明。 (对此有任何评论将不胜感激)
关于Python Twisted,SSL 超时错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15020267/