[Twisted-Python] Question about writing a server that accepts multiple clients with independent processing
Gabriel Rossetti
mailing_lists at evotex.ch
Thu Feb 21 08:42:44 MST 2008
Phil Mayers wrote:
>>> You didn't by any chance use a class variable did you e.g.:
>>>
>>> class foo(...):
>>> my_data = []
>>> def dataReceived(self, data):
>>> self.my_data.append(data)
>>>
>> Yes, that must be it :
>>
>> class XmlStreamTestSrv(xmlstream.XmlStream):
>>
>> def __init__(self):
>> xmlstream.XmlStream.__init__(self)
>> self.message = []
>
> No, this is fine, as you say setting "self.foo" creates an instance
> variable.
>
> I personally don't use __init__ methods of the protocol because I
> believe some protocols make complex use of this, but it should be fine.
>
>> ...
>>
>> even though I though that in python if you put a "self." in front it
>> was an instance variable and not a class variable. I have been also
>> having some strange problems, like if I overload
>>
>> def connectionMade(self):
>>
>> it never gets called, even though the parent class (XmlStream) also
>> has it, and also I can't call self.transport.getPeer() or
>> xmlstream.XmlStream.transport.getPeer(), I get :
>>
>> print 'Connection from %s!' %
>> str(xmlstream.XmlStream.transport.getPeer())
>> exceptions.AttributeError: 'NoneType' object has no attribute
>> 'getPeer'
>>
>> so maybe something is wrong somewhere.
>
> It sounds like the protocol isn't being hooked up to the transport.
>
>>> ...is wrong. "my_data" is shared by all instances of the class and
>>> is mutable. You'll need to create instance variables, usually (I
>>> believe) as part of the factory process.
>> Ok, I'll look into that, thanks.
>>>
>>> If you can write a minimal example showing the problem, someone can
>>> probably tell you what you're doing wrong.
>>>
>> Ok, thanks, here's a minimal example :
>>
>> from twisted.words.xish import xmlstream, domish
>> from twisted.internet import reactor, protocol
>> from twisted.internet.protocol import Protocol, Factory
>> from twisted.words.xish import xpath
>>
>>
>> class XmlStreamTestSrv(xmlstream.XmlStream):
>>
>> def __init__(self):
>> xmlstream.XmlStream.__init__(self)
>> self.message = []
>>
>> def connectionMade(self): # never called, why?
>> print 'Connected :' #, string(self.transport.getPeer().host)
>>
>> def _onHeader(self, element):
>> #print "got header from % : %s" %
>> (str(self.transport.getPeer().host), element.toXml())
>> self.message.append(element.toXml())
>>
>> def _connected(self, xs):
>> #print 'Connection from %s!' %
>> str(xmlstream.XmlStream.transport.getPeer().host)
>> xs.addObserver("/header", self._onHeader)
>>
>> if __name__ == "__main__":
>>
>> c = XmlStreamTestSrv()
>>
>> f = xmlstream.XmlStreamFactory()
>> #f.addBootstrap(xmlstream.STREAM_CONNECTED_EVENT, c._connected)
>> f.addBootstrap(xmlstream.STREAM_START_EVENT, c._connected)
>>
>> reactor.listenTCP(4321, f)
>> reactor.run()
>
> Ah - you need to set the "protocol" attribute on the factory to the
> protocol *class*, and then when a connection is made the class will be
> instantiated and connected to the transport. This is why
> self.transport is None, and because you're using an instance of the
> protocol, the data is getting squashed together. Do this:
>
> f = xmlstream.XmlStreamFactory()
> f.protocol = XmlStreamTestSrv
> reactor.listenTCP(4321, f)
> reactor.run()
>
Ahh, ok, I get it, and I should therefor subclass
xmlstream.XmlStreamFactory and add the bootstrap there, something like :
class MyXmlStreamFactory(xmlstream.XmlStreamFactory):
protocol = XmlStreamTestSrv
def buildProtocol(self, *pargs, **kwargs):
p = xmlstream.XmlStreamFactory.buildProtocol(self, *pargs,
**kwargs)
addBootstrap(xmlstream.STREAM_START_EVENT, p._connected)
return p
Regards,
Gabriel Rossetti
More information about the Twisted-Python
mailing list