2010-09-03 14 views
6

के साथ यूडीपी क्लाइंट और सर्वर मैं एक सर्वर और क्लाइंट बनाना चाहता हूं जो ट्विस्टेड का उपयोग करके नेटवर्क से यूडीपी पैकेट भेजता है और प्राप्त करता है। मैंने इसे पहले ही पाइथन में सॉकेट के साथ लिखा है, लेकिन ट्विस्टेड कॉलबैक और थ्रेडिंग फीचर्स का लाभ लेना चाहते हैं। हालांकि, मुझे ट्विस्ट के डिजाइन के साथ मदद की ज़रूरत है।ट्विस्ट पायथन

मैं पैकेट मैं प्राप्त करना चाहते हैं आपके पास अनेक प्रकार है, लेकिन नाटक करते हैं वहाँ से एक है:

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) 

मैं एक प्रोटोकॉल वर्ग (उदाहरण के लगभग प्रत्यक्ष प्रतिलिपि) है, जो जब काम करने के लिए लगता है बना रहा एक अन्य कार्यक्रम से डेटा भेजने:

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

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

क्या मैं नहीं जानता है कि कैसे मैं एक ग्राहक जो नेटवर्क है, जो रिएक्टर द्वारा उठाया हो पर मनमाने ढंग से पैकेट भेज सकते हैं बना सकता हूँ:

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

मुझे क्लाइंट और सर्वर पर पुन: उपयोग पता ध्वज सेट करना भी सुनिश्चित करना है ताकि मैं एक ही डिवाइस पर एक ही समय में प्रत्येक के कई उदाहरण चला सकूं (उदा। एक स्क्रिप्ट दिल की धड़कन भेज रही है, दूसरा दिल की धड़कन, आदि का जवाब देता है)।

क्या कोई मुझे दिखा सकता है कि यह ट्विस्ट के साथ कैसे किया जा सकता है?

अद्यतन:

यह मैं इसे कैसे पायथन में सॉकेट के साथ क्या है। मैं एक ही समय में कई श्रोताओं और प्रेषकों को चला सकता हूं और वे सभी एक-दूसरे को सुनते हैं। मैं इस परिणाम को मुड़कर कैसे प्राप्त करूं? (सुनने भाग एक अलग प्रक्रिया होना जरूरी नहीं है।)

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()) 

कार्य समाधान:

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() 

उत्तर

12

बस ऊपर सर्वर उदाहरण की तरह, एक क्लाइंट उदाहरण है। यह मदद करनी चाहिए आप आरंभ:

ठीक है, यहाँ एक सरल हृदय की धड़कन प्रेषक और प्राप्तकर्ता आंकड़ारेख प्रोटोकॉल का उपयोग है।

from twisted.internet.protocol import DatagramProtocol 
from twisted.internet import reactor 
from twisted.internet.task import LoopingCall 
import sys, time 

class HeartbeatSender(DatagramProtocol): 
    def __init__(self, name, host, port): 
     self.name = name 
     self.loopObj = None 
     self.host = host 
     self.port = port 

    def startProtocol(self): 
     # Called when transport is connected 
     # I am ready to send heart beats 
     self.loopObj = LoopingCall(self.sendHeartBeat) 
     self.loopObj.start(2, now=False) 

    def stopProtocol(self): 
     "Called after all transport is teared down" 
     pass 

    def datagramReceived(self, data, (host, port)): 
     print "received %r from %s:%d" % (data, host, port) 


    def sendHeartBeat(self): 
     self.transport.write(self.name, (self.host, self.port)) 



class HeartbeatReciever(DatagramProtocol): 
    def __init__(self): 
     pass 

    def startProtocol(self): 
     "Called when transport is connected" 
     pass 

    def stopProtocol(self): 
     "Called after all transport is teared down" 


    def datagramReceived(self, data, (host, port)): 
     now = time.localtime(time.time()) 
     timeStr = str(time.strftime("%y/%m/%d %H:%M:%S",now)) 
     print "received %r from %s:%d at %s" % (data, host, port, timeStr) 



heartBeatSenderObj = HeartbeatSender("sender", "127.0.0.1", 8005) 

reactor.listenMulticast(8005, HeartbeatReciever(), listenMultiple=True) 
reactor.listenMulticast(8005, heartBeatSenderObj, listenMultiple=True) 
reactor.run() 

प्रसारण उदाहरण बस उपरोक्त दृष्टिकोण को संशोधित करता है:

from twisted.internet.protocol import DatagramProtocol 
from twisted.internet import reactor 
from twisted.internet.task import LoopingCall 
import sys, time 

class HeartbeatSender(DatagramProtocol): 
    def __init__(self, name, host, port): 
     self.name = name 
     self.loopObj = None 
     self.host = host 
     self.port = port 

    def startProtocol(self): 
     # Called when transport is connected 
     # I am ready to send heart beats 
     self.transport.joinGroup('224.0.0.1') 
     self.loopObj = LoopingCall(self.sendHeartBeat) 
     self.loopObj.start(2, now=False) 

    def stopProtocol(self): 
     "Called after all transport is teared down" 
     pass 

    def datagramReceived(self, data, (host, port)): 
     print "received %r from %s:%d" % (data, host, port) 


    def sendHeartBeat(self): 
     self.transport.write(self.name, (self.host, self.port)) 



class HeartbeatReciever(DatagramProtocol): 
    def __init__(self, name): 
     self.name = name 

    def startProtocol(self): 
     "Called when transport is connected" 
     self.transport.joinGroup('224.0.0.1') 
     pass 

    def stopProtocol(self): 
     "Called after all transport is teared down" 


    def datagramReceived(self, data, (host, port)): 
     now = time.localtime(time.time()) 
     timeStr = str(time.strftime("%y/%m/%d %H:%M:%S",now)) 
     print "%s received %r from %s:%d at %s" % (self.name, data, host, port, timeStr) 



heartBeatSenderObj = HeartbeatSender("sender", "224.0.0.1", 8005) 

reactor.listenMulticast(8005, HeartbeatReciever("listner1"), listenMultiple=True) 
reactor.listenMulticast(8005, HeartbeatReciever("listner2"), listenMultiple=True) 
reactor.listenMulticast(8005, heartBeatSenderObj, listenMultiple=True) 
reactor.run() 
+0

मुझे इन उदाहरणों को Google की सहायता से मिला, लेकिन वे मेरी समस्याओं का समाधान नहीं करते हैं। – Jake

+0

@ जेक क्या यह सॉकेट पुन: उपयोग की समस्या का समाधान करता है या आप कुछ और ढूंढ रहे हैं? – pyfunc

+0

+1 यह काम करता है, लेकिन चूंकि यह मल्टीकास्ट का उपयोग कर रहा है क्योंकि सुनने वाले रिएक्टरों में से केवल एक प्रेषक डेटा निकाल रहा है। यह मुझे जो कुछ भी ढूंढ रहा है उसके करीब थोड़ा लाता है, जो सभी सुनने वाले ग्राहकों के लिए एक प्रसारण है। (आपको मल्टीकास्ट की तलाश करने वाले लोगों के लिए यह उदाहरण छोड़ना चाहिए!) – Jake

1

चेक बाहर echoclient_udp.py उदाहरण।

के बाद से यूडीपी काफी क्लाइंट और सर्वर के बीच सममित है, तो आप सिर्फ अपने पैकेट भेजने के लिए भी वहाँ reactor.listenUDP को चलाने के लिए, सर्वर (जो वास्तव में सिर्फ भेजे गए पैकेट के लिए डिफ़ॉल्ट गंतव्य सेट) के लिए connect, तो transport.write चाहते हैं।

+0

आप सुझाव दे रहे हैं मैं reactor.listenUDP दो बार (एक बार सर्वर के साथ और एक बार ग्राहक के साथ) कहते हैं और फिर reactor.run कहते हैं? मैं कोशिश नहीं कर सकता क्योंकि मैंने पुन: उपयोग पता नहीं लगाया है, इसलिए मुझे नहीं पता कि वह वास्तव में काम करता है या नहीं। – Jake

+0

मैं सुझाव देता हूं कि आप प्रत्येक सॉकेट पर एक बार सुनें, संभावित रूप से अलग प्रक्रियाओं में, और फिर प्रत्येक प्रक्रिया में 'reactor.run'। प्रत्येक प्रक्रिया के लिए आपको एक अलग (आईपी, पोर्ट) संयोजन होना चाहिए। मुझे समझ में नहीं आता कि इस पर पुन: उपयोगकर्ता कहां आता है? – poolie

संबंधित मुद्दे