Je souhaite créer un serveur et un client qui envoie et reçoit des paquets UDP à partir du réseau à l'aide de Twisted. J'ai déjà écrit ceci avec des sockets en Python, mais je veux profiter des fonctionnalités de rappel et de threading de Twisted. Cependant, j'ai besoin d'aide avec le design de Twisted.Client UDP et serveur avec Twisted Python
Je dispose de plusieurs types de paquets que je veux recevoir, mais Feignons il n'y a qu'un seul:
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)
J'ai fait une classe de protocole (copie presque directe des exemples), ce qui semble fonctionner quand je envoyer des données d'un autre programme:
class MyProtocol(DatagramProtocol):
def datagramReceived(self, data, (host, port)):
p = Packet(data)
print p
reactor.listenUDP(3000, MyProtocol())
reactor.run()
Ce que je ne sais pas comment puis-je créer un client qui peut envoyer des paquets arbitraires sur le réseau, qui sont repris par le réacteur:
# Something like this:
s = Sender()
p = Packet()
p.packet_type = 3
s.send(p.pack())
p.packet_type = 99
s.send(p.pack())
Je dois également m'assurer de définir l'indicateur d'adresse de réutilisation sur le client et les serveurs afin que je puisse exécuter plusieurs instances de chaque en même temps sur le même périphérique (par ex. un script envoie des battements de cœur, un autre répond aux battements de cœur, etc.). Quelqu'un peut-il me montrer comment cela pourrait être fait avec Twisted?
Mise à jour:
Voici comment je le fais avec les sockets en Python. Je peux courir plusieurs auditeurs et expéditeurs en même temps et ils s'entendent tous. Comment obtenir ce résultat avec Twisted? (La partie d'écoute ne doit pas être un processus distinct.)
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())
solution de travail:
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()
J'ai trouvé ces exemples moi-même avec l'aide de Google, mais ils ne traitent pas les problèmes que je rencontre. – Jake
@Jake Est-ce que cela résout le problème de la réutilisation du socket ou si vous cherchez autre chose? – pyfunc
+1 Cela fonctionne, mais comme il utilise la multidiffusion, seul l'un des réacteurs d'écoute reçoit les données que l'expéditeur est en train d'émettre. Cela me rapproche un peu plus de ce que je cherche, qui est une diffusion pour tous les clients qui écoutent. (Vous devriez laisser cet exemple comme c'est pour les personnes à la recherche de multidiffusion!) – Jake