2
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()

On the code above, when i enter the url "https: //localhost/echo" from the web browser, it gets the page. After 5 seconds later i try to reload the page, it does not refresh the web page, stuck on reloading operation. On the second attempt of reload, it gets the page instantly.

When i run the code above with reactor.listenTCP(8080, factory), no such problem occurs. (I can reload page without stucking reload and get the page instantly)

Problem can be repeated with Chrome, Firefox. But when i try it with Ubuntu's Epiphany browser, no such problem occurs.

I could not understand why this occurs.

Any comment about understanding/solving problem will be appriciated.

Extra info:

  • When i use listenSSL, file descriptor related with the connection does not close after timeout seconds later. While reloading page it stays still, and on the second reload operation, it is closed and new file descriptor is opened. (and i get page instantly)
  • When i use listenTCP, file descriptor closes after timeout seconds later, and when i reload page it opens new file descriptor and return page instantly.
  • Also with Telnet connection, it timeout connections as expected in both case.
  • Twisted client that connects this server also affects timeouts as expected.
4

1 回答 1

1

The class that timeout connection is TimeoutMixin class.

and it uses transport.loseConneciton() method to timeout connections.

Somehow, DefaultOpenSSLFactory uses the connection(?), therefore loseConnection method waits for finishing the transportation and at that time it doesn't accept any process on the connection.

According to twisted documentation:

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.

As a result, when i change loseConnection() with abortConnection() on timeoutMixinClass via overriding it, situation is no more occuring.

When i clarify the reason of why loseConnection is not enough to close connection on specific situations, i'll note it here. (any comment about it will be appreciated)

于 2013-02-25T10:17:49.283 回答