[Twisted-web] Telnet chat server
Drew Smathers
drew.smathers at gmail.com
Thu Jun 4 19:06:11 EDT 2009
2009/6/3 Jason St.Clair <woahyeahyeah at yahoo.com>:
> I've got a simple little chat server set up that people can telnet into. The code is as follows:
>
> ----------
>
> from twisted.internet import reactor
> from twisted.internet.protocol import ServerFactory
> from twisted.protocols.basic import LineOnlyReceiver
> import threading
>
> class ChatProtocol(LineOnlyReceiver):
>
> name = ""
>
> def getName(self):
> if self.name!="":
> return self.name
> return self.transport.getPeer().host
>
> def connectionMade(self):
> print "New connection from "+self.getName()
> self.sendLine("Welcome to the chat.\r\n/quit to quit.")
> self.factory.sendMessageToAllClients(self.getName()+" joined the chat.")
> self.factory.clientProtocols.append(self)
>
> def connectionLost(self, reason):
> print "Lost connection from "+self.getName()
> self.factory.clientProtocols.remove(self)
> self.factory.sendMessageToAllClients(self.getName()+" disconnected.")
>
> def lineReceived(self, line):
> if line=="/quit":
> self.transport.loseConnection()
> else:
> self.factory.sendMessageToAllClients(self.getName()+": "+line)
>
> def sendLine(self, line):
> self.transport.write(line+"\r\n")
>
> class ChatProtocolFactory(ServerFactory):
>
> protocol = ChatProtocol
>
> def __init__(self):
> self.clientProtocols = []
>
> def sendMessageToAllClients(self, mesg):
> for client in self.clientProtocols:
> client.sendLine(mesg)
>
> def Test():
> global test
> factory.sendMessageToAllClients('Hey.')
> test = threading.Timer(1.0, Test)
> test.start()
> test = threading.Timer(1.0, Test)
> test.start()
>
> print "Starting Server"
> factory = ChatProtocolFactory()
> reactor.listenTCP(3009, factory)
> reactor.run()
>
> ----------
>
> The problem is that last def, "def Test()". It should send the line "Hey." to all connected users every second. It does that - however, the message only sends through if the client is typing or has entered a line. So, if a client is idle for 30 seconds, then starts typing, he will receive "Hey." 30 times in a row - one for each second he was idle.
>
> Is there any way to get this to send the message and have it show up for a client even when they're idle?
> _______________________________________________
> Twisted-web mailing list
> Twisted-web at twistedmatrix.com
> http://twistedmatrix.com/cgi-bin/mailman/listinfo/twisted-web
>
>
You should use twisted.internet.task.LoopingCall instead of
threading.Timer and it's also worth mentioning that twisted APIs are
*not* thread-safe; in use cases where you have to use threads (there
are really few), you should use reactor.callFromThread().
So the equivalent for the above using LoopingCall would be something like:
def test():
factory.sendMessageToAllClients('Hey.')
task = LoopingCall(test)
reactor.callWhenRunning(task.start, 1.0, 0)
...
HTH
-Drew
More information about the Twisted-web
mailing list