Whelk 6 Newbie Poster

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()
Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.