I found a nice little example chat server written in Python using Twisted. The problem I'm having is identifying each connected client in a way that I can use to send info to specific clients. So in the chat server situation, it'd be used to send private messages. I've spent a few days scouring the Internet for ways to do this and making educated guesses, but to no avail. Here's the chat server code:
from twisted.internet import reactor
from twisted.internet.protocol import ServerFactory
from twisted.protocols.basic import LineOnlyReceiver
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("Send '/NAME [new name]' to change your name.")
self.sendLine("Send '/EXIT' to quit.")
self.factory.sendMessageToAllClients(self.getName()+" has joined the party.")
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()+" has disconnected.")
def lineReceived(self, line):
print self.getName()+": "+line
if line[:5]=="/NAME":
oldName = self.getName()
self.name = line[5:].strip()
self.factory.sendMessageToAllClients(oldName+" changed name to "+self.getName())
elif line=="/EXIT":
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)
print "Starting Server"
factory = ChatProtocolFactory()
reactor.listenTCP(3001, factory)
reactor.run()
The last def in there is "sendMessageToAllClients(self, mesg)". I'm trying to come up with something that will send messages only to specific clients instead of all of them. Any assistance/pointing in the right direction would be greatly appreciated.
I did find this on twisted's site under the FAQ, and I think it might be trying to explain how to do what I'm trying to do, but I can't make any sense of it for the life of me.
How do I make input on one connection result in output on another? ΒΆ
This seems like it's a Twisted question, but actually it's a Python question. Each Protocol object represents one connection; you can call its transport.write to write some data to it. These are regular Python objects; you can put them into lists, dictionaries, or whatever other data structure is appropriate to your application.
As a simple example, add a list to your factory, and in your protocol's connectionMade and connectionLost, add it to and remove it from that list. Here's the Python code:
from twisted.internet.protocol import Protocol, Factory from twisted.internet import reactor class MultiEcho(Protocol): def connectionMade(self): self.factory.echoers.append(self) def dataReceived(self, data): for echoer in self.factory.echoers: echoer.transport.write(data) def connectionLost(self, reason): self.factory.echoers.remove(self) class MultiEchoFactory(Factory): protocol = MultiEcho def __init__(self): self.echoers = [] reactor.listenTCP(4321, MultiEchoFactory()) reactor.run()