Persistent connection in twisted

前端 未结 1 537
臣服心动
臣服心动 2020-11-30 14:37

I\'m new in Twisted and have one question. How can I organize a persistent connection in Twisted? I have a queue and every second checks it. If have some - send on client. I

相关标签:
1条回答
  • 2020-11-30 15:27

    Without knowing how the snippet you provided links into your internet.XXXServer or reactor.listenXXX (or XXXXEndpoint calls), its hard to make head-or-tails of it, but...

    First off, in normal use, a twisted protocol.Protocol's dataReceived would only be called by the framework itself. It would be linked to a client or server connection directly or via a factory and it would be automatically called as data comes into the given connection. (The vast majority of twisted protocols and interfaces (if not all) are interrupt based, not polling/callLater, thats part of what makes Twisted so CPU efficient)

    So if your shown code is actually linked into Twisted via a Server or listen or Endpoint to your clients then I think you will find very bad things will happen if your clients ever send data (... because twisted will call dataReceived for that, which (among other problems) would add extra reactor.callLater callbacks and all sorts of chaos would ensue...)

    If instead, the code isn't linked into twisted connection framework, then your attempting to reuse twisted classes in a space they aren't designed for (... I guess this seems unlikely because I don't know how non-connection code would learn of a transport, unless your manually setting it...)

    The way I've been build building models like this is to make a completely separate class for the polling based I/O, but after I instantiate it, I push my client-list (server)factory into the polling instance (something like mypollingthing.servfact = myserverfactory) there-by making a way for my polling logic to be able to call into the clients .write (or more likely a def I built to abstract to the correct level for my polling logic)

    I tend to take the examples in Krondo's Twisted Introduction as one of the canonical examples of how to do twisted (other then twisted matrix), and the example in part 6, under "Client 3.0" PoetryClientFactory has a __init__ that sets a callback in the factory.

    If I try blend that with the twistedmatrix chat example and a few other things, I get: (You'll want to change sendToAll to whatever your self.orders_queue.has_new_orders() is about)

    #!/usr/bin/python
    
    from twisted.internet import task
    from twisted.internet import reactor
    from twisted.internet.protocol import Protocol, ServerFactory
    
    class PollingIOThingy(object):
        def __init__(self):
            self.sendingcallback = None # Note I'm pushing sendToAll into here in main
            self.iotries = 0
    
        def pollingtry(self):
            self.iotries += 1
            print "Polling runs: " + str(self.iotries)
            if self.sendingcallback:
                self.sendingcallback("Polling runs: " + str(self.iotries) + "\n")
    
    class MyClientConnections(Protocol):
        def connectionMade(self):
            print "Got new client!"
            self.factory.clients.append(self)
    
        def connectionLost(self, reason):
            print "Lost a client!"
            self.factory.clients.remove(self)
    
    class MyServerFactory(ServerFactory):
        protocol = MyClientConnections
    
        def __init__(self):
            self.clients = []
    
        def sendToAll(self, message):
          for c in self.clients:
            c.transport.write(message)
    
    def main():
        client_connection_factory = MyServerFactory()
    
        polling_stuff = PollingIOThingy()
    
        # the following line is what this example is all about:
        polling_stuff.sendingcallback = client_connection_factory.sendToAll
        # push the client connections send def into my polling class
    
        # if you want to run something ever second (instead of 1 second after
        # the end of your last code run, which could vary) do:
        l = task.LoopingCall(polling_stuff.pollingtry)
        l.start(1.0) 
        # from: https://twistedmatrix.com/documents/12.3.0/core/howto/time.html
    
        reactor.listenTCP(5000, client_connection_factory)
        reactor.run()
    
    if __name__ == '__main__':
      main()
    

    To be fair, it might be better to inform PollingIOThingy of the callback by passing it as an arg to it's __init__ (that is what is shown in Krondo's docs), For some reason, I tend to miss connections like this when I read code and find class-cheating easier to see, but that may just by my personal brain-damage.

    0 讨论(0)
提交回复
热议问题