[Twisted-Python] LineReceiver Protocol
![](https://secure.gravatar.com/avatar/1f31b219cdd0dfc289095a32887a3405.jpg?s=120&d=mm&r=g)
Is there a way to extend the LineReceiver protocol to take action on a continued, periodic basis? Currently, the protocol only does work when a line is received. However, there are times when the script should take action without waiting to receive a line. For example, suppose a connection should be closed if it has been idle for more than X minutes. However, if connection is idle, it will not be sending commands. If no commands are sent, then no lines are received, which means there is no way to close the connection. Another example might be a global message that needs to be sent to all connections. The message would have to be stored in message queue and sent only when lineReceived is called. It would be nice if the message could instead be sent imediately even if the connection was currently idle.
![](https://secure.gravatar.com/avatar/46f609c9bea026767ebae519e0656656.jpg?s=120&d=mm&r=g)
On Sat, 20 Nov 2004 23:12:18 -0800, Michael Mata <michael.mata@gaigen.net> wrote:
Is there a way to extend the LineReceiver protocol to take action on a continued, periodic basis? Currently, the protocol only does work when a line is received. However, there are times when the script should take action without waiting to receive a line.
It doesn't have anything to do with the protocol; what you want is reactor.callLater(seconds, functionToCall) http://twistedmatrix.com/documents/current/howto/time has more information.
Another example might be a global message that needs to be sent to all connections. The message would have to be stored in message queue and sent only when lineReceived is called. It would be nice if the message could instead be sent imediately even if the connection was currently idle.
For this you just want to keep track of all the protocols you want to send stuff to. doc/examples/chatserver.py shows how to do this. basically, in your lineReceived, you can do something like "for prot in self.factory.protocols: prot.sendMessage(line)". -- Twisted | Christopher Armstrong: International Man of Twistery Radix | Release Manager, Twisted Project ---------+ http://radix.twistedmatrix.com
![](https://secure.gravatar.com/avatar/1f31b219cdd0dfc289095a32887a3405.jpg?s=120&d=mm&r=g)
Christopher Armstrong wrote:
On Sat, 20 Nov 2004 23:12:18 -0800, Michael Mata <michael.mata@gaigen.net> wrote:
Is there a way to extend the LineReceiver protocol to take action on a continued, periodic basis? Currently, the protocol only does work when a line is received. However, there are times when the script should take action without waiting to receive a line.
It doesn't have anything to do with the protocol; what you want is reactor.callLater(seconds, functionToCall)
http://twistedmatrix.com/documents/current/howto/time has more information.
Another example might be a global message that needs to be sent to all connections. The message would have to be stored in message queue and sent only when lineReceived is called. It would be nice if the message could instead be sent imediately even if the connection was currently idle.
For this you just want to keep track of all the protocols you want to send stuff to. doc/examples/chatserver.py shows how to do this. basically, in your lineReceived, you can do something like "for prot in self.factory.protocols: prot.sendMessage(line)".
The function task.LoopingCall(runEverySecond) from twisted.internet looks like a good fit for scheduling recurring maintenance. If I follow chatserver.py, data globally available to all protocols should be stored in the reactor. I'm guessing that if I want data associated to a specific instance of a protocol, I should store it in a variable under the protocol's __init__ function. For example, I'd give a protocol a session id upon connection and add it to the client list in the reactor. Now if I want to send a message to that client, I'd iterate throught the list in the reactor until I find the one with correct session id.
![](https://secure.gravatar.com/avatar/fb44df761a72cca8686ea7faf897344b.jpg?s=120&d=mm&r=g)
Christopher Armstrong wrote:
On Sat, 20 Nov 2004 23:12:18 -0800, Michael Mata <michael.mata@gaigen.net> wrote:
Is there a way to extend the LineReceiver protocol to take action on a continued, periodic basis? Currently, the protocol only does work when a line is received. However, there are times when the script should take action without waiting to receive a line.
It doesn't have anything to do with the protocol; what you want is reactor.callLater(seconds, functionToCall)
http://twistedmatrix.com/documents/current/howto/time has more information.
Another example might be a global message that needs to be sent to all connections. The message would have to be stored in message queue and sent only when lineReceived is called. It would be nice if the message could instead be sent imediately even if the connection was currently idle.
For this you just want to keep track of all the protocols you want to send stuff to. doc/examples/chatserver.py shows how to do this. basically, in your lineReceived, you can do something like "for prot in self.factory.protocols: prot.sendMessage(line)".
The function task.LoopingCall(runEverySecond) from twisted.internet looks like a good fit for scheduling recurring maintenance.
If I follow chatserver.py, data globally available to all protocols should be stored in the reactor.
No, the reactor is pretty much off-limits for storing user data :) You should store such information in your client Factory. You can use the Factory's buildProtocol method to do per-protocol record keeping.
I'm guessing that if I want data associated to a specific instance of a protocol, I should store it in a variable under the protocol's __init__ function.
Sure, that's fine, and you can pass state in to your Protocol instances when you build them from your Factory's buildProtocol.
For example, I'd give a protocol a session id upon connection and add it to the client list in the reactor. Now if I want to send a message to that client, I'd iterate throught the list in the reactor until I find the one with correct session id.
Sure, except s/reactor/Factory/ -Eric
![](https://secure.gravatar.com/avatar/1f31b219cdd0dfc289095a32887a3405.jpg?s=120&d=mm&r=g)
Michael Mata wrote:
Christopher Armstrong wrote:
On Sat, 20 Nov 2004 23:12:18 -0800, Michael Mata <michael.mata@gaigen.net> wrote:
Is there a way to extend the LineReceiver protocol to take action on a continued, periodic basis? Currently, the protocol only does work when a line is received. However, there are times when the script should take action without waiting to receive a line.
It doesn't have anything to do with the protocol; what you want is reactor.callLater(seconds, functionToCall)
http://twistedmatrix.com/documents/current/howto/time has more information.
The function task.LoopingCall(runEverySecond) from twisted.internet looks like a good fit for scheduling recurring maintenance.
Where should task.LoopingCall(runEverySecond) be placed? I'm currently using internet.TCPServer, which is passed the port number and a protocol factory. The protocol inherits from basic.LineReceiver. I tried placing the task in the factory's __init__ function, but it doesn't seem to run.
![](https://secure.gravatar.com/avatar/7ed9784cbb1ba1ef75454034b3a8e6a1.jpg?s=120&d=mm&r=g)
On Sun, 21 Nov 2004 17:48:15 -0800, Michael Mata <michael.mata@gaigen.net> wrote:
Michael Mata wrote:
I tried placing the task in the factory's __init__ function, but it doesn't seem to run.
My mistake. The task does run when placed in the factory's __init__ function.
Factory.startFactory() is a better place for it (and stopping the loop in Factory.stopFactory() is appropriate as well). __init__ is called when the Application is instantiated. start* is called when the application is run. stop* is called when the application is stopped. With a tac file, instantiation occurs at almost exactly when run does. With other forms of application configuration, this may not be true. Jp
participants (4)
-
Christopher Armstrong
-
Eric Mangold
-
Jp Calderone
-
Michael Mata