Mike
Mike

Reputation: 7831

Twisted share a variable between tcp/udp protocols

I have the following tcpserver simple example. I'm looking to share the factor counter var with a udp server so on each connect it will inc the value for both tcp and udp. So if i connect first with tcp it will be 2 then if I connect to the port on udp.. it will be 3

#!/usr/bin/env python

from twisted.internet.protocol import Factory, Protocol
from twisted.internet import reactor

class TCP(Protocol):

    def connectionMade(self):
        self.factory.counter += 1
        self.transport.write(str(self.factory.counter)+'\r\n')
        self.transport.loseConnection()

class QOTDFactory(Factory):

    def __init__(self, protocol='tcp'):
        if protocol == 'tcp':
            self.protocol = TCP
        else:
            self.protocol = UDP

        self.counter = 1

reactor.listenTCP(8007, QOTDFactory('tcp'))
#reactor.listenUDP(8007, QOTDFactory('udp'))

reactor.run()

My main issue is starting up a UDP class that will work along side.. that is my sticking point. I think how i reference the counter is ok and will work

Upvotes: 2

Views: 1433

Answers (3)

Jean-Paul Calderone
Jean-Paul Calderone

Reputation: 48335

The argument to reactor.listenUDP should be a DatagramProtocol instance, as shown in the UDP example: http://twistedmatrix.com/documents/current/core/howto/udp.html. You can't use your QOTDFactory with UDP, so it doesn't need the TCP vs UDP selection logic. Instead, just make a DatagramProtocol subclass with your desired protocol logic and let it share a reference to the factory used by your TCP server.

#!/usr/bin/env python

from twisted.internet.protocol import Factory, Protocol
from twisted.internet import reactor

class StreamCounter(Protocol):
    def connectionMade(self):
        self.factory.counter += 1
        self.transport.write(str(self.factory.counter)+'\r\n')
        self.transport.loseConnection()


class DatagramCounter(DatagramProtocol):
    def __init__(self, factory):
        self.factory = factory

    def datagramReceived(self, data, address):
        self.factory.counter += 1
        self.transport.write(str(self.factory.counter), address)


class QOTDFactory(Factory):
    counter = 0
    protocol = StreamCounter


factory = QOTDFactory()
reactor.listenTCP(8007, factory)
reactor.listenUDP(8007, DatagramCounter(factory))

reactor.run()

I renamed TCP and UDP to StreamCounter and DatagramCounter, since they're not limited to use with TCP and UDP respectively (and those weren't terrible descriptive names ;). For example, you'll be able to use StreamCounter over SSL using reactor.listenSSL as well.

Upvotes: 4

Bryan Austin
Bryan Austin

Reputation: 497

Does this work for your needs?

#!/usr/bin/env python

from twisted.internet.protocol import Factory, Protocol
from twisted.internet import reactor

class Counter():
  def __init__(self):
    self.count = 0

class TCP(Protocol):

    def connectionMade(self):
        self.factory.counter.count += 1
        self.transport.write(str(self.factory.counter)+'\r\n')
        self.transport.loseConnection()

class QOTDFactory(Factory):

    def __init__(self, protocol, counter):
        if protocol == 'tcp':
            self.protocol = TCP
        else:
            self.protocol = UDP

        self.counter = counter

counter = Counter()
reactor.listenTCP(8007, QOTDFactory('tcp', counter))
reactor.listenUDP(8007, QOTDFactory('udp', counter))

reactor.run()

Upvotes: 1

gecco
gecco

Reputation: 18850

You could use a static class variable to implement this counter:

class QOTDFactory(Factory):
    counter = 1

    def __init__(self, protocol='tcp'):
        if protocol == 'tcp':
            self.protocol = TCP
        else:
            self.protocol = UDP

        QOTDFactory.counter += 1

Upvotes: 0

Related Questions