Twisted Deferred with periodical calls - python

My Problem looks like this:
I have a Twisted Server, which sends values every 2 seconds over TCP with callLater. And I have a twisted client, which recieves the values and should handle the recieving value with a deferred.
My Server looks like this:
from twisted.internet.protocol import ServerFactory
from twisted.protocols.basic import NetstringReceiver
from random import randint
class ServerProtocol(NetstringReceiver):
def __init__(self, factory):
self.factory = factory
self.sendObject = None
def connectionMade(self):
self.sendValue()
def connectionLost(self, reason):
sendObject, self.sendObject = self.sendObject, None
sendObject.cancel()
def sendValue(self):
data = randint(2,20)
self.sendString(str(data))
print('send: {0}'.format(data))
from twisted.internet import reactor
self.sendObject = reactor.callLater(2, self.sendValue)
class MyServerFactory(ServerFactory):
def __init__(self):
self.protsa = []
def buildProtocol(self, addr):
return ServerProtocol(self)
def setCallback(self, callback):
self.callback = callback
def serverMain():
factory = MyServerFactory()
# factory.setCallback(generateVal)
from twisted.internet import reactor
port = reactor.listenTCP(2345, factory, interface='127.0.0.1')
print 'Serving on %s.' % (port.getHost())
reactor.run()
if __name__ == '__main__':
serverMain()
My Client looks like this:
from twisted.internet.protocol import ClientFactory
from twisted.protocols.basic import NetstringReceiver
from twisted.internet import defer
class ClientProtocol(NetstringReceiver):
def stringReceived(self, string):
print("recieved")
self.factory.printValue(string)
def connectionMade(self):
print("Made Connection")
def connetionLost(self):
print("Connection Lost")
class MyClientFactory(ClientFactory):
protocol = ClientProtocol
def __init__(self, deferred):
self.deferred = deferred
def clientConnectionFailed(self, connector, reason):
if self.deferred is not None:
d, self.deferred = self.deferred, None
d.errback(reason)
def printValue(self, value):
if self.deferred is not None:
d, self.deferred = self.deferred, None
d.callback(value)
def OutputValue(host, port):
d = defer.Deferred()
from twisted.internet import reactor
factory = MyClientFactory(d)
reactor.connectTCP(host, port, factory)
return d
def clientMain():
def writeError(err):
print("Deferred Error!\n")
print("Error: {0}".format(err.__str__))
def writeValue(value):
print("Value revieved: {0}".format(value))
from twisted.internet import reactor
d = OutputValue('127.0.0.1', 2345)
d.addCallbacks(writeValue, writeError)
reactor.run()
if __name__ == '__main__':
clientMain()
Output:
Made Connection
recieved
Value revieved: 11
recieved
recieved
recieved
For the first time everything works fine. After connection the server sends a value which the client recieves. The client handels the with a deferred as wished. The second value are not handled by the deferred. I also expected that because the deferred are only fired once.
Now I would like to have a possibility to handle every recieved value by a deferred, so I can also do error handling.
I had a look at this:
Twisted: deferred that fires repeatedly
Re-using deferred objects in Twisted
but I cannot get hold of a solution for my problem. This can't be so unusual.
Or do I have to disconnect and connect every time?

A Deferred is an object which represents the result of a specific request that you are making. But since a request can only have one associated response, in the same way that a function can only return once, a Deferred can only be fired once.
You already have a function - printValue - which is run when a value is received and should be printed. Why not just print the value in that function right away, rather than going looking for a Deferred which your caller set up?

Related

Why sending a simple string message from client to PodSixNet server is not working

How to make my first communication between client and server by sending a simple string message, I've followed all the documentation, tutorials and topics based on PodSixNet and I can't do it in any way for a few days..
Thank you very much!
Server Code
`
from PodSixNet.Channel import Channel
from PodSixNet.Server import Server
from time import sleep
class ClientChannel(Channel):
def Network(self, data):
print(data)
def Network_myaction(self, data):
print("myaction", data)
class MyServer(Server):
channelClass = ClientChannel
def Connected(self, channel, addr):
print('New connection: {}'.format(channel, addr))
if __name__ == "__main__":
print("Server starting on LOCALHOST...\n")
myserver = MyServer(localaddr=('MyLocalIP', 1337))
while True:
myserver.Pump()
sleep(0.0001)
Client Code
from PodSixNet.Connection import ConnectionListener
from PodSixNet.Connection import connection
from time import sleep
class DouaIntrebari(ConnectionListener):
def __init__(self, host, port, **kwargs):
self.Connect((host, port))
super().__init__(**kwargs)
self.say = "Message Received !"
self.nr1 = 1
self.nr2 = 2
self.running = False
while not self.running:
self.Pump()
connection.Pump()
sleep(0.01)
def send_info(self):
if self.nr1 < self.nr2:
self.Send({"action": "zice", "say": self.say})
if __name__ == "__main__":
print("Client started.\n")
DouaIntrebari('MyLocalIP', 1337)
`
I tried to trigger a method to send the string message to the server but nothing happens...

Callback function does not see correct values in instance

I'm having a strange phenomena in Python with callback functions and handlers.
I use ZMQ to handle my communication and use a stream for the socket. I have the base class:
import multiprocessing
import zmq
from concurrent.futures import ThreadPoolExecutor
from zmq.eventloop import ioloop, zmqstream
from zmq.utils import jsonapi as json
# Types of messages
TYPE_A = 'type_a'
TYPE_B = 'type_b'
class ZmqProcess(multiprocessing.Process):
def __init__(self):
super(ZmqProcess, self).__init__()
self.context = None
self.loop = None
self.handle_stream = None
def setup(self):
self.context = zmq.Context()
self.loop = ioloop.IOLoop.instance()
def send(self, msg_type, msg, host, port):
sock = zmq.Context().socket(zmq.PAIR)
sock.connect('tcp://%s:%s' % (host, port))
sock.send_json([msg_type, msg])
def stream(self, sock_type, addr):
sock = self.context.socket(sock_type)
if isinstance(addr, str):
addr = addr.split(':')
host, port = addr if len(addr) == 2 else (addr[0], None)
if port:
sock.bind('tcp://%s:%s' % (host, port))
else:
port = sock.bind_to_random_port('tcp://%s' % host)
stream = zmqstream.ZMQStream(sock, self.loop)
return stream, int(port)
class MessageHandler(object):
def __init__(self, json_load=-1):
self._json_load = json_load
self.pool = ThreadPoolExecutor(max_workers=10)
def __call__(self, msg):
i = self._json_load
msg_type, data = json.loads(msg[i])
msg[i] = data
if msg_type.startswith('_'):
raise AttributeError('%s starts with an "_"' % msg_type)
getattr(self, msg_type)(*msg)
And I have a class that inherits from it:
import zmq
import zmq_base
class ZmqServerMeta(zmq_base.ZmqProcess):
def __init__(self, bind_addr, handlers):
super(ZmqServerMeta, self).__init__()
self.bind_addr = bind_addr
self.handlers = handlers
def setup(self):
super(ZmqServerMeta, self).setup()
self.handle_stream, _ = self.stream(zmq.PAIR, self.bind_addr)
self.handle_stream.on_recv(StreamHandler(self.handle_stream, self.stop,
self.handlers))
def run(self):
self.setup()
self.loop.start()
def stop(self):
self.loop.stop()
class StreamHandler(zmq_base.MessageHandler):
def __init__(self, handle_stream, stop, handlers):
super(StreamHandler, self).__init__()
self._handle_stream = handle_stream
self._stop = stop
self._handlers = handlers
def type_a(self, data):
if zmq_base.TYPE_A in self._handlers:
if self._handlers[zmq_base.TYPE_A]:
for handle in self._handlers[zmq_base.TYPE_A]:
self.pool.submit(handle, data)
else:
pass
else:
pass
def type_b(self, data):
if zmq_base.TYPE_B in self._handlers:
if self._handlers[zmq_base.TYPE_B]:
for handle in self._handlers[zmq_base.TYPE_B]:
self.pool.submit(handle, data)
else:
pass
else:
pass
def endit(self):
self._stop()
Additionally, I have a class that I want to use as storage. And here is where the trouble starts:
import threading
import zmq_server_meta as server
import zmq_base as base
class Storage:
def __init__(self):
self.list = []
self.list_lock = threading.RLock()
self.zmq_server = None
self.host = '127.0.0.1'
self.port = 5432
self.bind_addr = (self.host, self.port)
def setup(self):
handlers = {base.TYPE_A: [self. remove]}
self.zmq_server = server.ZmqServerMeta(handlers=handlers, bind_addr=self.bind_addr)
self.zmq_server.start()
def add(self, data):
with self.list_lock:
try:
self.list.append(data)
except:
print "Didn't work"
def remove(self, msg):
with self.list_lock:
try:
self.list.remove(msg)
except:
print "Didn't work"
The idea is that that class stores some global information that it receives.
It is all started in a file to test:
import sys
import time
import storage
import zmq_base as base
import zmq_server_meta as server
def printMsg(msg):
print msg
store = storage.Storage()
store.setup()
handlers = {base.TYPE_B: [printMsg]}
client = server.ZmqServerMeta(handlers=handlers, bind_addr=('127.0.0.1', 5431))
client.start()
message = "Test"
store.add(message)
client.send(base.TYPE_A, message, '127.0.0.1', 5432)
I simplified it to reduce clutter. Instead of just adding it, it is usually send and then a response comes back. The response, the client sending, should be processed by the correct callback, remove(), and it should remove something out of the list. The problem that occurs is, that the remove() function sees an empty list, although there should be an element in the list. If I check from the testing file, I can see the element after it was added, and if I call remove() from there, I see a non-empty list and can remove it. My question is, why does the callback sees an empty list and how can I make sure it does see the correct elements in the list?
Kind regards
Patrick
I believe the problem lays in the fact that the ZmqProcess class inherits from multiprocessing.Process. Multiprocessing does not allow to share objects among different processes, except by using a shared memory map using Value or Array ( as can be seen in the documentation: https://docs.python.org/3/library/multiprocessing.html#sharing-state-between-processes )
If you want to use your custom object, you can use a Server process / proxy object, which can be found in on the same page of the documentation.
So you can, for instance, define a manager in the init function of the Storage class like: self.manager = Manager() Afterwards you put self.list = self.manager.list(). This should do the trick.

Asynchronous client in Twisted not sending / receiving request (using NetStringReceiver)

I am trying to do asynchronous programming using Twisted. What I'm trying to do is create a client which will pass query parameters (in my case, hash type and hash value) and wait for the server's response. I am currently using NetstringReceiver for the parameters. However, am having these problems:
The client is not able to send its request to the server, and
The client hangs forever when I ran it. It seems that there is a callback that's not returning.
Below are the codes for the client and server.
This code is actually based on this tutorial by Dave Peticolas.
Client Code
import os, sys, argparse
from twisted.internet import defer
from twisted.internet.protocol import Protocol, ClientFactory
from twisted.protocols.basic import NetstringReceiver
class QueryProtocol(Protocol):
response = ''
def dataReceived(self, data):
self.response = data
def connectionLost(self, reason):
self.responseReceived(self.response)
def responseReceived(self, response):
self.factory.response_finished(response)
class QueryFactory(ClientFactory):
protocol = QueryProtocol
def __init__(self, deferred):
self.deferred = deferred
def response_finished(self, response):
if self.deferred is not None:
d, self.deferred = self.deferred, None
d.callback(response)
def clientConnectionFailed(self, connector, reason):
if self.deferred is not None:
d, self.deferred = self.deferred, None
d.errback(reason)
class QueryNetProtocol(NetstringReceiver):
def connectionMade(self):
self.sendRequest(self.factory.hash_type, self.factory.hash_value)
def sendRequest(self, hash_type, hash_value):
self.sendString(hash_type + '.' + hash_value)
def stringReceived(self, s):
self.transport.loseConnection()
self.responseReceived(s)
def responseReceived(self, response):
self.factory.handleResponse(response)
class QueryNetFactory(ClientFactory):
protocol = QueryNetProtocol
def __init__(self, hash_type, hash_value):
self.hash_type = hash_type
self.hash_value = hash_value
self.deferred = defer.Deferred()
def handleResponse(self, response):
d, self.deferred = self.deferred, None
d.callback(response)
def clientConnectionLost(self, _, reason):
if self.deferred is not None:
d, self.deferred = self.deferred, None
d.errback(reason)
clientConnectionFailed = clientConnectionLost
class QueryProxy(object):
def __init__(self, host, port):
self.host = host
self.port = port
def query(self, hash_type, hash_value):
factory = QueryNetFactory(hash_type, hash_value)
from twisted.internet import reactor
reactor.connectTCP(self.host, self.port, factory)
return factory.deferred
def perform_query(host, port):
d = defer.Deferred()
from twisted.internet import reactor
factory = QueryFactory(d)
reactor.connectTCP(host, port, factory)
return d
def main(options):
done = False
query_result = ""
host = options.host
port = int(options.port)
sha1 = options.sha1
proxy = QueryProxy(host, port)
from twisted.internet import reactor
def process_query_result(response):
d = proxy.query('sha1', sha1)
def fail(err):
print "Problem in processing response : %s" % err
return response
return d.addErrback(fail)
def query_ok(response):
query_result = response
done = True
def query_failed(err):
print "Problem in query : %s" % err
done = True
def query_done(_):
if done == True: reactor.stop()
d = perform_query(host, port)
d.addCallback(process_query_result)
d.addCallbacks(query_ok, query_failed)
d.addBoth(query_done)
reactor.run()
print "The result of the query is : %s" % query_result
if __name__ == "__main__":
parser = argparse.ArgumentParser()
parser.add_argument("host", help="server host/ip")
parser.add_argument("port", help="server port number to listen to")
parser.add_argument("-sha1", help="sha1 value to be queried")
options = parser.parse_args()
main(options)
Server Code
import os, sys, argparse
from twisted.internet.protocol import ServerFactory
from twisted.protocols.basic import NetstringReceiver
class GridQueryService(object):
def query(self, hash_type, hash_value):
print "this is the query service. Type is %s and value is %s" % (hash_type, hash_value)
return hash_value
class GridQueryProtocol(NetstringReceiver):
def stringReceived(self, request):
print >>sys.stderr, request
if '.' not in request:
self.transport.loseConnection()
return
hash_type, hash_value = request.split('.')
self.formRequestReceived(hash_type, hash_value)
def formRequestReceived(self, hash_type, hash_value):
found_flag = self.factory.query(hash_type, hash_value)
if found_flag: self.sendString(str(found_flag))
self.transport.loseConnection()
class GridQueryFactory(ServerFactory):
protocol = GridQueryProtocol
def __init__(self, service):
self.service = service
def query(self, hash_type, hash_value):
return self.service.query(hash_type, hash_value)
def main(options):
grid_query_service = GridQueryService()
grid_query_factory = GridQueryFactory(grid_query_service)
from twisted.internet import reactor
port = reactor.listenTCP(int(options.port), grid_query_factory, interface=options.host)
print "Serving GRID query service on %s" % str(port.getHost())
reactor.run()
if __name__ == "__main__":
parser = argparse.ArgumentParser()
parser.add_argument("host", help="server host/ip")
parser.add_argument("port", help="server port number to listen to")
options = parser.parse_args()
main(options)
Any ideas on how to resolve this? Thanks in advance. Help is greatly appreciated!
Your server may use netstrings and your client may contain code for using netstrings, but your client doesn't use netstrings.
main calls perform_query. perform_query makes a QueryFactory which connects a QueryProtocol which never sends any data and doesn't have any logic related to handling netstrings even if it did.
I've updated my client. Revised client code is below.
I am now able to send request. Here are the outputs:
Sent request!
String received!
Handling response!
I'm called!
Connection lost! - QueryNetFactory
As you can see, the callback process_query_result callback has been fired. However, the other callbacks were not and I can't still receive the data/result using the QueryFactory/QueryProtocol. I have a suspect that it's about the deferred and callbacks, but I'm quite confused.
In initializing the QueryFactory class, should I really create a new deferred? If yes, how will it realize/know the callbacks added to the original deferred (the one that was returned by the perform_query method)? Now if in case I should not create a new deferred, how can I fire the callbacks added in the original deferred in the 'responseReceived' method of the QueryProtocol?
Client Code
class QueryProtocol(Protocol):
response = ''
def dataReceived(self, data):
print "Data received!"
self.response = data
def connectionLost(self, reason):
print "Connection lost!"
self.responseReceived(self.response)
def responseReceived(self, response):
print "Response received!"
self.factory.response_finished(response)
class QueryFactory(ClientFactory):
protocol = QueryProtocol
def __init__(self):
self.deferred = defer.Deferred()
def response_finished(self, response):
print "Response finished!"
if self.deferred is not None:
d, self.deferred = self.deferred, None
d.callback(response)
def clientConnectionFailed(self, connector, reason):
print "Client connection failed! - QueryFactory"
if self.deferred is not None:
d, self.deferred = self.deferred, None
d.errback(reason)
class QueryNetProtocol(NetstringReceiver):
def connectionMade(self):
self.sendRequest(self.factory.hash_type, self.factory.hash_value)
def sendRequest(self, hash_type, hash_value):
print "Sent request!"
self.sendString(hash_type + '.' + hash_value)
def stringReceived(self, s):
print "String received!"
self.transport.loseConnection()
self.responseReceived(s)
def responseReceived(self, response):
self.factory.handleResponse(response)
class QueryNetFactory(ClientFactory):
protocol = QueryNetProtocol
def __init__(self, deferred, hash_type, hash_value):
self.hash_type = hash_type
self.hash_value = hash_value
self.deferred = deferred
def handleResponse(self, response):
print "Handling response!"
d, self.deferred = self.deferred, None
d.callback(response)
def clientConnectionLost(self, _, reason):
print "Connection lost! - QueryNetFactory"
if self.deferred is not None:
d, self.deferred = self.deferred, None
d.errback(reason)
clientConnectionFailed = clientConnectionLost
class QueryProxy(object):
def __init__(self, host, port):
self.host = host
self.port = port
def query(self):
factory = QueryFactory()
from twisted.internet import reactor
reactor.connectTCP(self.host, self.port, factory)
return factory.deferred
def perform_query(host, port, hash_type, hash_value):
d = defer.Deferred()
from twisted.internet import reactor
factory = QueryNetFactory(d, hash_type, hash_value)
reactor.connectTCP(host, port, factory)
return d
def main(options):
done = False
query_result = ""
host = options.host
port = int(options.port)
sha1 = options.sha1
proxy = QueryProxy(host, port)
from twisted.internet import reactor
def process_query_result(response):
print "I'm called!"
d = proxy.query()
def fail(err):
print "Process query result failure : %s" % err
return d.addErrback(fail)
def query_ok(response):
print "query ok!"
query_result = response
done = True
def query_failed(err):
print "Problem in query : %s" % err
done = True
def query_done(_):
if done == True: reactor.stop()
d = perform_query(host, port, "sha1", sha1)
d.addCallback(process_query_result)
d.addCallbacks(query_ok, query_failed)
d.addBoth(query_done)
reactor.run()
print "The result of the query is : %s" % query_result
Again, any help is greatly appreciated! Thanks!

Stopping a Reactor kills All Reactors Running on Different Ports

I'm trying to implement this code, in which each "node" is a self-contained "actor".
from twisted.internet.protocol import Protocol, Factory
from twisted.internet import reactor, defer
from twisted.protocols.basic import LineReceiver
class ChatProtocol(LineReceiver):
def __init__(self, factory):
self.factory = factory
self.name = None
self.state = "REGISTER"
def connectionMade(self):
self.sendLine("What's your name?")
def connectionLost(self, reason):
if self.name in self.factory.users:
del self.factory.users[self.name]
self.broadcastMessage("{} has left the channel.".format(self.name))
def lineReceived(self, line):
if self.state == "REGISTER":
self.handle_REGISTER(line)
else:
self.handle_CHAT(line)
def handle_REGISTER(self, name):
if name in self.factory.users:
self.sendLine("Name taken, please choose another!")
return
self.sendLine("Welcome, {}".format(name))
self.broadcastMessage("{} has joined the channel.".format(name))
self.name = name
self.factory.users[name] = self
self.state = "CHAT"
def handle_CHAT(self, message):
message = "[%s]>> %s" % (self.name, message)
self.broadcastMessage(message)
def broadcastMessage(self, message):
for name, protocol in self.factory.users.iteritems():
if protocol != self:
protocol.sendLine(message)
class ChatFactory(Factory):
"""Handle all the nodes' connection"""
def __init__(self):
self.users = {}
def buildProtocol(self, addr):
return ChatProtocol(self)
class Node:
def __init__(self, stop=None):
self.Factory = ChatFactory
self.reactor = reactor
self.d = defer.Deferred()
# with `stop` the node is bound to die
if stop:
self.reactor.callLater(stop, self.stop)
def listen(self, port):
self.reactor.listenTCP(port, self.Factory())
def run(self):
self.reactor.run()
def stop(self):
self.reactor.stop()
class Organization:
"""
An organization consists of several nodes, with one node as a leader
"""
def __init__(self):
self.nodes = []
def create_leader(self):
# create first node now with intentionally kill the leader's reactor after 5 seconds
leader_node = Node(5)
leader_node.listen(8000)
self.nodes.append(leader_node)
def create_more_nodes(self):
node_1 = Node()
node_2 = Node()
self.nodes.append(node_1)
self.nodes.append(node_2)
def activate(self):
self.nodes[1].listen(8001)
self.nodes[2].listen(8002)
"""
now leader_node listens at 8000
node_1 listens at 8001
node_2 listens at 8002
"""
# run each node's reactor
for n in self.nodes:
n.run()
if __name__ == '__main__':
org = Organization()
org.create_leader()
org.create_more_nodes()
org.activate()
After 5 seconds, the leader_node's reactor is stopped via Node.stop() that gets deferred. However, I have no idea why node_1 and node_2 listening at 8001 and 8002 were also stopped. If anyone with more experience with Twisted could point this out that'd be great!
reactor.run() means "run the entire program". While it does not forcibly terminate (the function does return), it only does so in order to allow you to clean up some state before exiting. So you should only ever run one reactor per process and exit shortly after it is finished.
If you want to have self-contained services which can shut down all of their incoming and outgoing connections as well as their listening ports, you have to track those connections in connectionMade and connectionLost. You also have to keep track of your listening port so that you can stopListening.
As a side note, listenTCP is a very low-level API that you probably shouldn't be calling directly; instead, use the high-level Endpoints API, which is much more flexible.
Here's a version of your code that tracks inbound and connections and listening ports and shuts them down as you'd like, while sharing a reactor between all the nodes.
from twisted.internet.protocol import Factory
from twisted.internet.endpoints import TCP4ServerEndpoint
from twisted.protocols.basic import LineReceiver
from twisted.internet.defer import Deferred
class ChatProtocol(LineReceiver):
def __init__(self, factory):
self.factory = factory
self.name = None
self.state = "REGISTER"
def connectionMade(self):
self.factory.node.activeTransports.append(self.transport)
self.sendLine("What's your name?")
def connectionLost(self, reason):
self.factory.node.activeTransports.remove(self.transport)
if self.name in self.factory.users:
del self.factory.users[self.name]
self.broadcastMessage("{} has left the channel.".format(self.name))
def lineReceived(self, line):
if self.state == "REGISTER":
self.handle_REGISTER(line)
else:
self.handle_CHAT(line)
def handle_REGISTER(self, name):
if name in self.factory.users:
self.sendLine("Name taken, please choose another!")
return
self.sendLine("Welcome, {}".format(name))
self.broadcastMessage("{} has joined the channel.".format(name))
self.name = name
self.factory.users[name] = self
self.state = "CHAT"
def handle_CHAT(self, message):
message = "[%s]>> %s" % (self.name, message)
self.broadcastMessage(message)
def broadcastMessage(self, message):
for name, protocol in self.factory.users.iteritems():
if protocol != self:
protocol.sendLine(message)
class ChatFactory(Factory):
"""Handle all the nodes' connection"""
def __init__(self, node):
self.users = {}
self.node = node
def buildProtocol(self, addr):
return ChatProtocol(self)
class Node:
def __init__(self, endpoint, clock, stop=None):
self.Factory = ChatFactory
self._endpoint = endpoint
self._listenStarting = None
self._listeningPort = None
self.activeTransports = []
if stop is not None:
print("Scheduling stop.", stop)
clock.callLater(stop, self.stop)
def listen(self):
self._listenStarting = self._endpoint.listen(self.Factory(self))
def setPort(port):
self._listeningPort = port
def clear(whatever):
self._listenStarting = None
return whatever
self._listenStarting.addCallback(setPort).addBoth(clear)
def stop(self):
if self._listenStarting is not None:
self._listenStarting.cancel()
if self._listeningPort is not None:
self._listeningPort.stopListening()
for transport in self.activeTransports[:]:
transport.abortConnection()
class Organization:
def __init__(self, reactor):
self.reactor = reactor
self.nodes = []
def port(self, number):
return TCP4ServerEndpoint(self.reactor, number)
def create_leader(self):
leader_node = Node(self.port(8000), self.reactor, 5)
leader_node.listen()
self.nodes.append(leader_node)
def create_more_nodes(self):
node_1 = Node(self.port(8001), self.reactor)
node_2 = Node(self.port(8002), self.reactor)
self.nodes.append(node_1)
self.nodes.append(node_2)
def activate(self):
self.nodes[1].listen()
self.nodes[2].listen()
def main(reactor):
org = Organization(reactor)
org.create_leader()
org.create_more_nodes()
org.activate()
return Deferred()
if __name__ == '__main__':
from twisted.internet.task import react
react(main)

Python, Call a class function within another class

Can you anyone please help me call the broadcast function from class BroadcastServerFactory in class test, as per attached code
I have tried so many methods of call a function from another class, but no solution
import sys
from twisted.internet import reactor
from twisted.python import log
from twisted.web.server import Site
from twisted.web.static import File
from autobahn.websocket import WebSocketServerFactory, \
WebSocketServerProtocol, \
listenWS
class test():
//call broadcast function from here
class BroadcastServerProtocol(WebSocketServerProtocol):
def onOpen(self):
self.factory.register(self)
def onMessage(self, msg, binary):
if not binary:
self.factory.broadcast("'%s' from %s" % (msg, self.peerstr))
def connectionLost(self, reason):
WebSocketServerProtocol.connectionLost(self, reason)
self.factory.unregister(self)
class BroadcastServerFactory(WebSocketServerFactory):
"""
Simple broadcast server broadcasting any message it receives to all
currently connected clients.
"""
def __init__(self, url, debug = False, debugCodePaths = False):
WebSocketServerFactory.__init__(self, url, debug = debug, debugCodePaths = debugCodePaths)
self.clients = []
self.tickcount = 0
self.tick()
def tick(self):
self.tickcount += 1
self.broadcast("'tick %d' from server" % self.tickcount)
reactor.callLater(1, self.tick)
def register(self, client):
if not client in self.clients:
print "registered client " + client.peerstr
self.clients.append(client)
def unregister(self, client):
if client in self.clients:
print "unregistered client " + client.peerstr
self.clients.remove(client)
def broadcast(self, msg):
print "broadcasting message '%s' .." % msg
for c in self.clients:
c.sendMessage(msg)
print "message sent to " + c.peerstr
if __name__ == '__main__':
if len(sys.argv) > 1 and sys.argv[1] == 'debug':
log.startLogging(sys.stdout)
debug = True
else:
debug = False
ServerFactory = BroadcastServerFactory
#ServerFactory = BroadcastPreparedServerFactory
factory = ServerFactory("ws://localhost:9000",
debug = debug,
debugCodePaths = debug)
factory.protocol = BroadcastServerProtocol
factory.setProtocolOptions(allowHixie76 = True)
listenWS(factory)
webdir = File(".")
web = Site(webdir)
reactor.listenTCP(8080, web)
reactor.run()
class test():
def __init__(self, factory):
factory.broadcast("I don't know what I'm doing!")
Meanwhile, in main...
factory = ServerFactory("ws://localhost:9000",
debug = debug,
debugCodePaths = debug)
test(factory)
This will do what you want, but it seems you're missing some core concepts about classes and instances. For the test class to call anything on another class, there needs to be an instance of it first (bar the case of static methods).

Categories