Quiero crear un servidor y cliente que envíe y reciba paquetes UDP de la red usando Twisted. Ya he escrito esto con sockets en Python, pero quiero aprovechar las características de devolución de llamada y subprocesamiento de Twisted. Sin embargo, necesito ayuda con el diseño de Twisted.Cliente y servidor UDP con Twisted Python
tengo varios tipos de paquetes que desea recibir, pero vamos a suponer que sólo hay una:
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 enviar 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 puedo crear un cliente que puede enviar paquetes arbitrarios en la red, que son recogidas 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 que pueda ejecutar varias instancias de cada uno al mismo tiempo en el mismo dispositivo (p. un script está enviando latidos, otro responde a latidos del corazón, etc.).
¿Alguien puede mostrarme cómo se puede hacer esto con Twisted?
actualización:
Así es como lo hago con tomas en Python. Puedo ejecutar múltiples oyentes y remitentes al mismo tiempo y todos se escuchan. ¿Cómo obtengo este resultado con Twisted? (La parte de escucha no tiene por qué 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()
Encontré estos ejemplos con la ayuda de Google, pero no solucionan los problemas que tengo. – Jake
@Jake ¿Resuelve esto el problema de la reutilización de socket o está buscando algo más? – pyfunc
+1 Esto funciona, pero como usa multidifusión, solo uno de los reactores de escucha está recibiendo los datos que el emisor está emitiendo. Eso me acerca un poco más a lo que estoy buscando, que es una transmisión para todos los clientes que escuchan. (¡Debe dejar este ejemplo como a las personas que buscan multidifusión!) – Jake