[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