Twisted: How to sendLine from outside the LineReceiver class?
Andrew Bennetts
andrew-pythonlist at puzzling.org
Sun Feb 29 19:51:49 EST 2004
[You'll probably get more answers to Twisted questions on the Twisted
mailing-list: twisted-python at twistedmatrix.com]
On Sun, Feb 29, 2004 at 02:06:07PM -0500, Qp wrote:
> Hello. I'm building a simple chat server and client interface, and I've got
> everything working except for this:
>
> While the client's basic.LineReceiver protocol class can sendLine when a
> connection is made (that is, when the class is called automatically),
> whenever I try to call sendLine from another class (my ClientFactory class)
> then I get the following error.
>
> "in sendLine
> return self.transport.write(line + self.delimiter)
> AttributeError: 'NoneType' object has no attribute 'write'"
>
> So, I assume the instance of the LineReceiver is not set up properly. How
> do I do this?
>
> The code I am using for the classes is as follows. The error comes when I
> call chatFactory.sendMessage():
>
[...]
> class chatFactory(protocol.ClientFactory):
> protocol = chatClient
>
[...]
> def sendMessage(self):
> c = chatClient()
> c.sendLine("Hey there")
I see you are using ClientFactory, so I presume you want to make a client
connection to a remote server with this protocol.
You need to connect your protocol, not just create the object out of thin
air. See:
http://twistedmatrix.com/documents/howto/clients
and also:
http://twistedmatrix.com/documents/current/api/twisted.internet.interfaces.IReactorTCP.html#connectTCP
I think the easiest way to do what you need is to have the protocol's
connectionMade signal the factory:
----
class ChatClient(basic.LineReceiver):
def connectionMade(self):
self.sendLine("A new person has entered the room!")
self.factory.clientReady(self)
def lineReceived(self, line):
app.text_output.config(state=NORMAL) #enable text_output for insert
app.text_output.insert(END, line +"\n")
app.text_output.config(state=DISABLED)
app.text_input.delete(0, END) #clear text_input
app.text_output.see(END) #move scrollbar to the bottom
def connectionLost(self, reason):
reactor.stop()
class ChatFactory(protocol.ClientFactory):
protocol = ChatClient
def clientConnectionFailed(self, connector, reason):
reactor.stop()
def clientConnectionLost(self, connector, reason):
reactor.stop()
def startFactory(self):
self.messageQueue = []
self.clientInstance = None
def clientReady(self, instance):
self.clientInstance = instance
for msg in self.messageQueue:
self.sendMessage(msg)
def sendMessage(self, msg='Hey there'):
if self.clientInstance is not None:
self.clientInstance.sendLine(msg)
else:
self.messageQueue.append(msg)
----
Note that I've added a simple message queue because it may take some time
for the connection to be established, so calls to sendMessage could fail if
called too soon. The queue avoids that problem.
A better solution might be to not write the factory at all, and use
twisted.internet.protocol.clientCreator:
http://twistedmatrix.com/documents/current/api/twisted.internet.protocol.ClientCreator.html
----
from twisted.python import log
# Create creator and connect
clientCreator = protocol.ClientCreator(reactor, ChatClient)
deferred = clientCreator.connectTCP(host, port)
# When connected, send a line
def connectionReady(protocol):
protocol.sendLine('Hey there')
deferred.addCallback(connectionReady)
# Log any errors that occur (such as connection failed)
deferred.addErrback(log.err)
----
-Andrew.
More information about the Python-list
mailing list