Cliente y servidor UDP con Twisted Python

Quiero crear un servidor y un cliente que envíe y reciba paquetes UDP de la red utilizando Twisted. Ya he escrito esto con sockets en Python, pero quiero aprovechar las características de devolución de llamada y subprocesos de Twisted. Sin embargo, necesito ayuda con el diseño de Twisted.

Tengo varios tipos de paquetes que quiero recibir, pero supongamos que solo hay uno:

class Packet(object):
    def __init__(self, data=None):
        self.packet_type = 1
        self.payload = ''
        self.structure = '!H6s'
        if data == None:
            return

        self.packet_type, self.payload = struct.unpack(self.structure, data)

    def pack(self):
        return struct.pack(self.structure, self.packet_type, self.payload)

    def __str__(self):
        return "Type: {0}\nPayload {1}\n\n".format(self.packet_type, self.payload)

Hice una clase de protocolo (copia casi directa de los ejemplos), que parece funcionar cuando envío datos desde otro programa:

class MyProtocol(DatagramProtocol):
    def datagramReceived(self, data, (host, port)):
        p = Packet(data)
        print p

reactor.listenUDP(3000, MyProtocol())
reactor.run()

Lo que no sé es cómo creo un cliente que pueda enviar paquetes arbitrarios en la red, que son recogidos por el reactor:

# Something like this:
s = Sender()
p = Packet()
p.packet_type = 3
s.send(p.pack())
p.packet_type = 99
s.send(p.pack())

También necesito asegurarme de configurar el indicador de dirección de reutilización en el cliente y los servidores para poder ejecutar varias instancias de cada una al mismo tiempo en el mismo dispositivo (por ejemplo, un script envía latidos, otro responde a latidos, etc.).

¿Alguien puede mostrarme cómo se podría hacer esto con Twisted?

Actualizar:

Así es como lo hago con sockets en Python. Puedo ejecutar múltiples oyentes y remitentes al mismo tiempo y todos se escuchan entre sí. ¿Cómo obtengo este resultado con Twisted? (La parte de escucha no necesita ser un proceso separado).

class Listener(Process):
    def __init__(self, ip='127.0.0.1', port=3000):
        Process.__init__(self)
        self.ip = ip
        self.port = port

    def run(self):
        sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        sock.bind((self.ip, self.port))

        data, from_ip = sock.recvfrom(4096)
        p = Packet(data)
        print p

class Sender(object):
    def __init__(self, ip='127.255.255.255', port=3000):
        self.sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        self.ip = (ip, port)

    def send(self, data):
        self.sock.sendto(data, self.ip)

if __name__ == "__main__":
    l = Listener()
    l.start()
    s = Sender()
    p = Packet()
    p.packet_type = 4
    p.payload = 'jake'
    s.send(p.pack())

Solución de trabajo:

class MySender(DatagramProtocol):
    def __init__(self, packet, host='127.255.255.255', port=3000):
        self.packet = packet.pack()
        self.host = host
        self.port = port

    def startProtocol(self):
        self.transport.write(self.packet, (self.host, self.port))

if __name__ == "__main__":
    packet = Packet()
    packet.packet_type = 1
    packet.payload = 'jake'

    s = MySender(packet)

    reactor.listenMulticast(3000, MyProtocol(), listenMultiple=True)
    reactor.listenMulticast(3000, s, listenMultiple=True)
    reactor.callLater(4, reactor.stop)
    reactor.run()

Respuestas a la pregunta(2)

Su respuesta a la pregunta