Chcę utworzyć serwer i klienta, który wysyła i odbiera pakiety UDP z sieci za pomocą Twisted. Pisałem już to z gniazdami w Pythonie, ale chcę skorzystać z funkcji zwrotnych i wątków Twisted. Jednak potrzebuję pomocy przy projektowaniu Twisted.Klient i serwer UDP z Twisted Python
Mam wiele typów pakietów Chcę otrzymywać, ale niech udawać, że jest tylko jeden:
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)
Zrobiłem klasę protokołu (prawie kopią przykładach), który wydaje się działać, kiedy wysyłanie danych z innego programu:
class MyProtocol(DatagramProtocol):
def datagramReceived(self, data, (host, port)):
p = Packet(data)
print p
reactor.listenUDP(3000, MyProtocol())
reactor.run()
Co nie wiem, to w jaki sposób utworzyć klienta, które można wysłać dowolne pakiety w sieci, które odebrano przez reaktorze:
# Something like this:
s = Sender()
p = Packet()
p.packet_type = 3
s.send(p.pack())
p.packet_type = 99
s.send(p.pack())
Muszę również ustawić flagę adresu ponownego użycia na kliencie i serwerach, aby móc uruchamiać wiele instancji jednocześnie na tym samym urządzeniu (np. jeden skrypt wysyła bicie serca, inny reaguje na bicie serca, itp.).
Czy ktoś może mi pokazać, jak można to zrobić z Twisted?
Aktualizacja:
To jak to zrobić z gniazd w Pythonie. Mogę jednocześnie uruchomić wielu słuchaczy i nadawców, a oni wszyscy się słyszą. Jak uzyskać ten wynik z Twisted? (Część słuchania nie musi być oddzielny proces.)
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())
Roztwór roboczy:
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()
Te przykłady znalazłem sam przy pomocy Google, ale nie rozwiązują one problemów, które mam. – Jake
@Jake Czy to rozwiązuje problem ponownego użycia gniazda lub szukasz czegoś innego? – pyfunc
+1 To działa, ale ponieważ używa multicastu, tylko jeden z reaktorów nasłuchujących odbiera dane wysyłane przez nadawcę. To zbliża mnie trochę do tego, czego szukam, co jest transmitowane do wszystkich klientów słuchających. (Powinieneś opuścić ten przykład, tak jak jest dla osób szukających multiemisji!) – Jake