[Twisted-web] Telnet chat server

Drew Smathers drew.smathers at gmail.com
Thu Jun 4 19:06:16 EDT 2009


2009/6/4 Drew Smathers <drew.smathers at gmail.com>:
> 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
>

Also, forgot to mention: This is a general question better asked at
twisted-python mailing list (not twisted-web).

-Drew



More information about the Twisted-web mailing list