Search code examples
pythontwisted

Twisted multiple responses for single request


I have one LineReceiver protocol and want to send two responses like this:

def handle_CLIENT(self, data):
    ...
    self.sendLine(r1.raw)
    ...
    self.sendLine(r2.raw)

Twisted merge two responses into one like in Multiple responses in Twisted. Client is proprietary, and I can't change it behaviour. What the right way to make it works? Thank you.

EDIT

def handle_CLIENT(self, data):
    ...
    self.sendLine(r1.raw)
    reactor.doIteration(0.5)
    ...
    self.sendLine(r2.raw)

This works for me, but I guess it is not the right way. Because I don't know how it will when will more then one client :)


Solution

  • That is definitely not the right way. Among other things, depending on what happens, that doIteration may cause an infinite loop, or a crash.

    What you want to use is callLater, which lets you run a function at some time in the future.

    What you are trying to do is force the two responses into two separate TCP segments, because your peer is buggy. For an explanation of why, see this Twisted FAQ. Be aware that this cannot work in the general case, and that your proprietary client is just broken.

    However, you can make it work most of the time by doing this:

    def handle_CLIENT(self, data):
        self.transport.pauseProducing()
        def sendFirstLine():
            self.sendLine(r1.raw)
        def sendSecondLine():
            self.sendLine(r2.raw)
            # now that we've sent the second line we can accept more requests; if
            # we accept requests in the middle, we might send responses interleaved
            # with each other, which will probably break your client
            self.transport.resumeProducing()
    
        reactor.callLater(0, sendFirstLine)
        reactor.callLater(0.5, sendSecondLine)
    

    Again, TCP is a byte-stream protocol, and even with a half-second delay, slow networks might cause your two responses to get glued together at some router in the middle between you and your client. You can't depend on this. But it might be good enough to get your out of your curren jam - and it's a heck of a lot better than calling doIteration and crashing your server :)