[Twisted-Python] MultiService puzzler
Hi all, I'm trying to build an app using MultiService. I need to have 2 services, one that listens for UDP datagrams and another that can send those datagrams to an ActiveMQ server via a Stomp client. I can set up the two services just fine, but I'm stuck with how to call the MQ service send method from the UDPServer instance. Some code to illustrate: class GetUDP(DatagramProtocol): def datagramReceived(self, datagram, address): print datagram,address #Send datagram to the queue server # I don't know how to access the send method for the Stomp client service! testq = internet.TCPClient(APPVARIABLES['queue_server'], int(APPVARIABLES['queue_port']), connections.StompClientFactory (username='',password='',queue='/queue/test')) testq.setName('Testq') testq.setServiceParent(MQService) #create a UDP listener #TODO: this should be driven by the config file #reactor.listenUDP(42000, GetUDP()) internet.UDPServer(42000,GetUDP()).setServiceParent(MQService) # Create an application as normal application = service.Application("MQExample") # Connect our MultiService to the application, just like a normal service. MQService.setServiceParent(application) Note: this is won't run exactly as is, but should give an idea of my problem. I've setup the ActiveMQ Stomp client as 'testq'. I've setup the UDPServer service to listen for UDP packets. I can get the UDP packets and print them, but I can't figure out how to hand them to my Stomp client's send() method. This is possible, right? Thanks, Don
On Dec 12, 2007 12:08 AM, Don Smith
Hi all,
I'm trying to build an app using MultiService. I need to have 2 services, one that listens for UDP datagrams and another that can send those datagrams to an ActiveMQ server via a Stomp client.
I can set up the two services just fine, but I'm stuck with how to call the MQ service send method from the UDPServer instance.
Some code to illustrate:
class GetUDP(DatagramProtocol):
def datagramReceived(self, datagram, address): print datagram,address #Send datagram to the queue server # I don't know how to access the send method for the Stomp client service!
testq = internet.TCPClient(APPVARIABLES['queue_server'], int(APPVARIABLES['queue_port']), connections.StompClientFactory (username='',password='',queue='/queue/test')) testq.setName('Testq') testq.setServiceParent(MQService)
#create a UDP listener #TODO: this should be driven by the config file #reactor.listenUDP(42000, GetUDP()) internet.UDPServer(42000,GetUDP()).setServiceParent(MQService) # Create an application as normal application = service.Application("MQExample")
# Connect our MultiService to the application, just like a normal service. MQService.setServiceParent(application)
Note: this is won't run exactly as is, but should give an idea of my problem. I've setup the ActiveMQ Stomp client as 'testq'. I've setup the UDPServer service to listen for UDP packets. I can get the UDP packets and print them, but I can't figure out how to hand them to my Stomp client's send() method. This is possible, right?
Thanks,
Don
_______________________________________________ Twisted-Python mailing list Twisted-Python@twistedmatrix.com http://twistedmatrix.com/cgi-bin/mailman/listinfo/twisted-python
The answer is really easy -- you don't need any twisted magic to do this, you just need to use standard Python mechanisms. Your UDP listener, when it receives some data, just needs a Python reference to your Stomp client. You could have stuffed a reference to the Stomp client in a module global variable (naughty!), or better, you could have stuffed it in an attribute of your GetUDP object. So you could change this line: internet.UDPServer(42000,GetUDP()).setServiceParent(MQService) to these lines: udpService = GetUDP() udpService.stompClient = testq # stuff it in! internet.UDPServer(42000,udpService).setServiceParent(MQService) Cheers, Christian
Thanks for your response, Christian!
However, this still does not work and I think it is related to the
StompClientFactory and the StompProtocol I'm using. I'm including those at
the end of this email so you can see what they do.
I changed my GetUDP class to this:
class GetUDP(DatagramProtocol):
def datagramReceived(self, datagram, address):
print datagram,address
#Send datagram to the queue server
stompclient.send(datagram)
And I changed the instantiation to what you gave me, but I get this error
when I get a UDP packet:
File "Agent_service_test.py", line 103, in datagramReceived
stompclient.send(datagram)
exceptions.NameError: global name 'stompclient' is not defined
Here are my stomp classes:
class StompProtocol(Protocol, stomper.Engine):
def __init__(self, username='', password='', queue=''):
stomper.Engine.__init__(self)
self.username = username
self.password = password
self.counter = 1
self.log = logging.getLogger("sender")
self.queue = queue
def connected(self, msg):
"""Once I've connected I want to subscribe to the message queue.
"""
stomper.Engine.connected(self, msg)
#self.log.info("Connected: session %s. Begining say hello." %
msg['headers']['session'])
#lc = LoopingCall(self.send)
#lc.start(1)
f = stomper.Frame()
f.unpack(stomper.subscribe(self.queue))
# ActiveMQ specific headers:
#
# prevent the messages we send comming back to us.
f.headers['activemq.noLocal'] = 'true'
return f.pack()
def ack(self, msg):
"""Processes the received message. I don't need to
generate an ack message.
"""
self.log.info("SENDER - received: %s " % msg['body'])
return stomper.NO_REPONSE_NEEDED
def send(self):
"""Send out a hello message periodically.
"""
self.log.info("Saying hello (%d)." % self.counter)
self.counter += 1
f = stomper.Frame()
f.unpack(stomper.send(self.queue, 'hello there (%d)' % self.counter
))
# ActiveMQ specific headers:
#
f.headers['persistent'] = 'true'
self.transport.write(f.pack())
def connectionMade(self):
"""Register with stomp server.
"""
cmd = stomper.connect(self.username, self.password)
self.transport.write(cmd)
def dataReceived(self, data):
"""Data received, react to it and respond if needed.
"""
msg = stomper.unpack_frame(data)
returned = self.react(msg)
if returned:
self.transport.write(returned)
class StompClientFactory(ReconnectingClientFactory):
def __init__(self, username='', password='',
queue='',queue_type='',config=''):
self.username=username
self.password=password
self.queue=queue
self.queue_type=queue_type
self.config_file=config
def buildProtocol(self, addr):
if self.queue_type =='config':
return ConfigurationProtocol(self.queue,self.config_file,
self.username, self.password)
else:
return StompProtocol(self.username, self.password, self.queue)
def clientConnectionLost(self, connector, reason):
"""Lost connection
"""
print 'Lost connection. Reason:', reason
def clientConnectionFailed(self, connector, reason):
"""Connection failed
"""
print 'Connection failed. Reason:', reason
ReconnectingClientFactory.clientConnectionFailed(self, connector,
reason)
On Dec 12, 2007 8:16 AM, Christian Simms
Hi all,
I'm trying to build an app using MultiService. I need to have 2 services, one that listens for UDP datagrams and another that can send those datagrams to an ActiveMQ server via a Stomp client.
I can set up the two services just fine, but I'm stuck with how to call
On Dec 12, 2007 12:08 AM, Don Smith
wrote: the MQ service send method from the UDPServer instance.
Some code to illustrate:
class GetUDP(DatagramProtocol):
def datagramReceived(self, datagram, address): print datagram,address #Send datagram to the queue server # I don't know how to access the send method for the Stomp client service!
testq = internet.TCPClient(APPVARIABLES['queue_server'], int(APPVARIABLES['queue_port']), connections.StompClientFactory (username='',password='',queue='/queue/test')) testq.setName('Testq') testq.setServiceParent(MQService)
#create a UDP listener #TODO: this should be driven by the config file #reactor.listenUDP(42000, GetUDP()) internet.UDPServer(42000,GetUDP()).setServiceParent(MQService) # Create an application as normal application = service.Application("MQExample")
# Connect our MultiService to the application, just like a normal service. MQService.setServiceParent(application)
Note: this is won't run exactly as is, but should give an idea of my problem. I've setup the ActiveMQ Stomp client as 'testq'. I've setup the UDPServer service to listen for UDP packets. I can get the UDP packets and print them, but I can't figure out how to hand them to my Stomp client's send() method. This is possible, right?
Thanks,
Don
_______________________________________________ Twisted-Python mailing list Twisted-Python@twistedmatrix.com http://twistedmatrix.com/cgi-bin/mailman/listinfo/twisted-python
The answer is really easy -- you don't need any twisted magic to do this, you just need to use standard Python mechanisms. Your UDP listener, when it receives some data, just needs a Python reference to your Stomp client. You could have stuffed a reference to the Stomp client in a module global variable (naughty!), or better, you could have stuffed it in an attribute of your GetUDP object. So you could change this line:
internet.UDPServer(42000,GetUDP()).setServiceParent(MQService)
to these lines:
udpService = GetUDP() udpService.stompClient = testq # stuff it in! internet.UDPServer(42000,udpService).setServiceParent(MQService)
Cheers, Christian
_______________________________________________ Twisted-Python mailing list Twisted-Python@twistedmatrix.com http://twistedmatrix.com/cgi-bin/mailman/listinfo/twisted-python
Ah, I realized I need to call the reference the stompClient like this '
self.stompClient'.
Unfortunately, what is returned by this:
testq = internet.TCPClient(APPVARIABLES['queue_server'],
int(APPVARIABLES['queue_port']), connections.StompClientFactory
(username='',password='',queue='/queue/test'))
is the StompClientFactory object, not the StompProtocol object which
contains the send() method.
So, any ideas on how I can reference the StompProtocol object (that is
created by the StompClientFactory) from the GetUDP object?
Thanks,
Don
On Dec 12, 2007 9:10 AM, Don Smith
Thanks for your response, Christian!
However, this still does not work and I think it is related to the StompClientFactory and the StompProtocol I'm using. I'm including those at the end of this email so you can see what they do.
I changed my GetUDP class to this:
class GetUDP(DatagramProtocol):
def datagramReceived(self, datagram, address): print datagram,address #Send datagram to the queue server stompclient.send(datagram)
And I changed the instantiation to what you gave me, but I get this error when I get a UDP packet:
File "Agent_service_test.py", line 103, in datagramReceived stompclient.send(datagram) exceptions.NameError: global name 'stompclient' is not defined
Here are my stomp classes:
class StompProtocol(Protocol, stomper.Engine):
def __init__(self, username='', password='', queue=''): stomper.Engine.__init__(self) self.username = username self.password = password self.counter = 1 self.log = logging.getLogger("sender") self.queue = queue
def connected(self, msg): """Once I've connected I want to subscribe to the message queue. """ stomper.Engine.connected(self, msg)
#self.log.info("Connected: session %s. Begining say hello." % msg['headers']['session']) #lc = LoopingCall(self.send) #lc.start(1)
f = stomper.Frame () f.unpack(stomper.subscribe(self.queue))
# ActiveMQ specific headers: # # prevent the messages we send comming back to us. f.headers['activemq.noLocal'] = 'true'
return f.pack()
def ack(self, msg): """Processes the received message. I don't need to generate an ack message.
""" self.log.info("SENDER - received: %s " % msg['body']) return stomper.NO_REPONSE_NEEDED
def send(self): """Send out a hello message periodically. """ self.log.info("Saying hello (%d)." % self.counter) self.counter += 1
f = stomper.Frame() f.unpack(stomper.send(self.queue, 'hello there (%d)' % self.counter))
# ActiveMQ specific headers: # f.headers['persistent'] = 'true'
self.transport.write(f.pack())
def connectionMade(self): """Register with stomp server. """ cmd = stomper.connect(self.username, self.password) self.transport.write(cmd)
def dataReceived(self, data): """Data received, react to it and respond if needed. """ msg = stomper.unpack_frame(data)
returned = self.react(msg)
if returned: self.transport.write(returned)
class StompClientFactory(ReconnectingClientFactory): def __init__(self, username='', password='', queue='',queue_type='',config=''): self.username=username self.password=password self.queue=queue self.queue_type=queue_type self.config_file=config
def buildProtocol(self, addr): if self.queue_type =='config': return ConfigurationProtocol(self.queue,self.config_file, self.username, self.password) else: return StompProtocol(self.username, self.password, self.queue)
def clientConnectionLost(self, connector, reason): """Lost connection """ print 'Lost connection. Reason:', reason
def clientConnectionFailed(self, connector, reason): """Connection failed """ print 'Connection failed. Reason:', reason ReconnectingClientFactory.clientConnectionFailed(self, connector, reason)
On Dec 12, 2007 8:16 AM, Christian Simms
wrote: Hi all,
I'm trying to build an app using MultiService. I need to have 2 services, one that listens for UDP datagrams and another that can send those datagrams to an ActiveMQ server via a Stomp client.
I can set up the two services just fine, but I'm stuck with how to call the MQ service send method from the UDPServer instance.
Some code to illustrate:
class GetUDP(DatagramProtocol):
def datagramReceived(self, datagram, address): print datagram,address #Send datagram to the queue server # I don't know how to access the send method for the Stomp client service!
testq = internet.TCPClient(APPVARIABLES['queue_server'], int(APPVARIABLES['queue_port']), connections.StompClientFactory (username='',password='',queue='/queue/test')) testq.setName('Testq') testq.setServiceParent(MQService)
#create a UDP listener #TODO: this should be driven by the config file #reactor.listenUDP(42000, GetUDP()) internet.UDPServer(42000,GetUDP()).setServiceParent(MQService) # Create an application as normal application = service.Application("MQExample")
# Connect our MultiService to the application, just like a normal service. MQService.setServiceParent(application)
Note: this is won't run exactly as is, but should give an idea of my problem. I've setup the ActiveMQ Stomp client as 'testq'. I've setup
On Dec 12, 2007 12:08 AM, Don Smith < donwsmith@gmail.com> wrote: the
UDPServer service to listen for UDP packets. I can get the UDP packets and print them, but I can't figure out how to hand them to my Stomp client's send() method. This is possible, right?
Thanks,
Don
_______________________________________________ Twisted-Python mailing list Twisted-Python@twistedmatrix.com http://twistedmatrix.com/cgi-bin/mailman/listinfo/twisted-python
The answer is really easy -- you don't need any twisted magic to do this, you just need to use standard Python mechanisms. Your UDP listener, when it receives some data, just needs a Python reference to your Stomp client. You could have stuffed a reference to the Stomp client in a module global variable (naughty!), or better, you could have stuffed it in an attribute of your GetUDP object. So you could change this line:
internet.UDPServer(42000,GetUDP()).setServiceParent(MQService)
to these lines:
udpService = GetUDP() udpService.stompClient = testq # stuff it in! internet.UDPServer(42000,udpService).setServiceParent(MQService)
Cheers, Christian
_______________________________________________ Twisted-Python mailing list Twisted-Python@twistedmatrix.com http://twistedmatrix.com/cgi-bin/mailman/listinfo/twisted-python
participants (2)
-
Christian Simms
-
Don Smith