2015-04-16 3 views
18

मैं एक मुड़ सर्वर है कि XML अनुरोधों की उम्मीद है और बदले में एक्सएमएल प्रतिक्रियाओं भेजता लागू करने के लिए करना चाहते हैं:ट्विस्टेड एक्सएमएलस्ट्रीम: घटनाओं से कैसे जुड़ें?

<request type='type 01'><content>some request content</content></request> 
<response type='type 01'><content>some response content</content></response> 
<request type='type 02'><content>other request content</content></request> 
<response type='type 02'><content>other response content</content></response> 

मैं एक मुड़ ग्राहक & सर्वर before कि साधारण तार का आदान-प्रदान और XML का उपयोग करने के लिए है कि विस्तार करने के लिए करने की कोशिश की पैदा की है, लेकिन मुझे यह पता लगाना प्रतीत नहीं होता कि इसे सही तरीके से कैसे सेट किया जाए।

client.py:

#!/usr/bin/env python 
# encoding: utf-8 

from twisted.internet    import reactor 
from twisted.internet.endpoints import TCP4ClientEndpoint, connectProtocol 
from twisted.words.xish.domish import Element, IElement 
from twisted.words.xish.xmlstream import XmlStream 

class XMLClient(XmlStream): 

    def sendObject(self, obj): 
     if IElement.providedBy(obj): 
      print "[TX]: %s" % obj.toXml() 
     else: 
      print "[TX]: %s" % obj 
     self.send(obj) 

def gotProtocol(p): 
    request = Element((None, 'request')) 
    request['type'] = 'type 01' 
    request.addElement('content').addContent('some request content') 
    p.sendObject(request) 

    request = Element((None, 'request')) 
    request['type'] = 'type 02' 
    request.addElement('content').addContent('other request content') 

    reactor.callLater(1, p.sendObject, request) 
    reactor.callLater(2, p.transport.loseConnection) 

endpoint = TCP4ClientEndpoint(reactor, '127.0.0.1', 12345) 
d = connectProtocol(endpoint, XMLClient()) 
d.addCallback(gotProtocol) 

from twisted.python import log 
d.addErrback(log.err) 

reactor.run() 

पहले स्ट्रिंग आधारित दृष्टिकोण का उल्लेख के रूप में, ग्राहक जब तक CTRL + सी idles। एक बार जब यह जा रहा है, तो यह ट्विस्ट XMPP example से कुछ प्रेरणा प्राप्त करेगा।

server.py:

#!/usr/bin/env python 
# encoding: utf-8 

from twisted.internet    import reactor 
from twisted.internet.endpoints import TCP4ServerEndpoint 
from twisted.words.xish.xmlstream import XmlStream, XmlStreamFactory 
from twisted.words.xish.xmlstream import STREAM_CONNECTED_EVENT, STREAM_START_EVENT, STREAM_END_EVENT 

REQUEST_CONTENT_EVENT = intern("//request/content") 

class XMLServer(XmlStream): 
    def __init__(self): 
     XmlStream.__init__(self) 
     self.addObserver(STREAM_CONNECTED_EVENT, self.onConnected) 
     self.addObserver(STREAM_START_EVENT,  self.onRequest) 
     self.addObserver(STREAM_END_EVENT,  self.onDisconnected) 
     self.addObserver(REQUEST_CONTENT_EVENT, self.onRequestContent) 

    def onConnected(self, xs): 
     print 'onConnected(...)' 

    def onDisconnected(self, xs): 
     print 'onDisconnected(...)' 

    def onRequest(self, xs): 
     print 'onRequest(...)' 

    def onRequestContent(self, xs): 
     print 'onRequestContent(...)' 

class XMLServerFactory(XmlStreamFactory): 
    protocol = XMLServer 

endpoint = TCP4ServerEndpoint(reactor, 12345, interface='127.0.0.1') 
endpoint.listen(XMLServerFactory()) 
reactor.run() 

client.py उत्पादन:

TX [127.0.0.1]: <request type='type 01'><content>some request content</content></request> 
TX [127.0.0.1]: <request type='type 02'><content>other request content</content></request> 

server.py उत्पादन:

onConnected(...) 
onRequest(...) 
onDisconnected(...) 

मेरे सवालों का:

  1. सर्वर किसी निश्चित XML टैग से मुकाबला करते समय निकाल दिए गए ईवेंट की सदस्यता कैसे ले सकता है? //request/content XPath क्वेरी मेरे लिए ठीक लगता है, लेकिन onRequestContent(...) :-(
  2. उपवर्गीकरण है XmlStream और XmlStreamFactory सब पर एक उचित दृष्टिकोण कहा जाता नहीं प्राप्त करता है? यह अपने आप आधार वर्ग द्वारा भेजे गए घटनाओं के लिए अजीब है क्योंकि XMLServer सदस्याएं महसूस करता है और उसके बाद पारित हो जाता है खुद (?) xs पैरामीटर के रूप में?!? मैं नहीं बल्कि XMLServer एक साधारण वर्ग बना दें और वर्ग के सदस्य के रूप में एक XmlStream वस्तु है? वहाँ एक विहित दृष्टिकोण है?
  3. मैं कैसे addErrback(...) तरह सर्वर पर एक त्रुटि हैंडलर जोड़ना होगा ग्राहक में? मुझे चिंता है कि अपवाद निगल जाएंगे (पहले हुआ), लेकिन मुझे नहीं लगता किकहां प्राप्त करें 0 से इसे संलग्न करने के लिए ...
  4. डिफ़ॉल्ट अनुरोध के बाद सर्वर पहले अनुरोध के बाद कनेक्शन बंद क्यों करता है? मैं XmlStream.onDocumentEnd(...)loseConnection() पर कॉल करता हूं; मैं उस विधि को ओवरराइड कर सकता था, लेकिन मुझे आश्चर्य है कि बंद होने का कोई कारण नहीं है, मुझे नहीं लगता है। क्या यह कनेक्शन खुला नहीं है जब तक कि इस पल के लिए जरूरी सभी संचार नहीं किए जाते हैं?

मुझे आशा है कि यह पोस्ट बहुत विशिष्ट नहीं माना जाएगा; नेटवर्क पर एक्सएमएल की बात करना आम है, लेकिन डेढ़ दिन की तलाश के बावजूद, मैं कोई भी ट्विस्ट एक्सएमएल सर्वर उदाहरण नहीं ढूंढ पाया। हो सकता है कि मैं इसे भविष्य में किसी भी प्रश्न के साथ जंपस्टार्ट में बदलूं ...

+0

क्या आपको बिल्कुल XMLStream का उपयोग करना है? एक्सएमएल, आखिरकार, बस पाठ है। तो, इसे पाठ के रूप में भेजें, और ग्राहकों को इसके बारे में समझ में आता है हालांकि आप कृपया। चाहे वह एक्सएमएल, जेसन, या सादा पाठ है। –

उत्तर

1

यह ज्यादातर अनुमान है लेकिन जहां तक ​​मुझे पता है कि आपको इसे बंद किए बिना एक स्टांजा भेजकर स्ट्रीम खोलने की आवश्यकता है।

अपने उदाहरण में जब आप <request type='type 01'><content>some request content</content></request> भेज सर्वर start document रूप <request> छंद देखता है लेकिन उसके बाद आप </request> भेजने और सर्वर है कि के रूप में end document देखेंगे।

असल में, अपने सर्वर <request> शुरू दस्तावेज़ के रूप में खपत और वह भी क्यों अपने xpath, //request/content,, मेल नहीं होगा, क्योंकि सब उस तत्व की बाईं है <content>...</content> है।

पहले ग्राहक से <stream> जैसे कुछ भेजने का प्रयास करें, फिर दो अनुरोध और फिर </stream>

इसके अलावा, XmlStream उपclassing ठीक है जब तक आप सुनिश्चित करते हैं कि आप डिफ़ॉल्ट रूप से किसी भी तरीके को ओवरराइड नहीं करते हैं।

1

XmlStream का "केवल" प्रासंगिक घटक SAX पार्सर है। यहाँ कैसे मैं XmlStream और केवल XML पार्सिंग कार्यों का उपयोग कर एक अतुल्यकालिक SAX पार्सर लागू किया गया है:

server.py

from twisted.words.xish.domish import Element 
from twisted.words.xish.xmlstream import XmlStream 

class XmlServer(XmlStream): 
    def __init__(self): 
     XmlStream.__init__(self) # possibly unnecessary 

    def dataReceived(self, data): 
     """ Overload this function to simply pass the incoming data into the XML parser """ 
     try: 
      self.stream.parse(data)  # self.stream gets created after self._initializestream() is called 
     except Exception as e: 
      self._initializeStream() # reinit the DOM so other XML can be parsed 

    def onDocumentStart(self, elementRoot): 
     """ The root tag has been parsed """ 
     print('Root tag: {0}'.format(elementRoot.name)) 
     print('Attributes: {0}'.format(elementRoot.attributes)) 

    def onElement(self, element): 
     """ Children/Body elements parsed """ 
     print('\nElement tag: {0}'.format(element.name)) 
     print('Element attributes: {0}'.format(element.attributes)) 
     print('Element content: {0}'.format(str(element))) 

    def onDocumentEnd(self): 
     """ Parsing has finished, you should send your response now """ 
     response = domish.Element(('', 'response')) 
     response['type'] = 'type 01' 
     response.addElement('content', content='some response content') 
     self.send(response.toXml()) 

तो फिर तुम एक फैक्टरी वर्ग है कि इस प्रोटोकॉल का उत्पादन करेगा (बनाते हैं तो आप जो ' मैंने दिखाया कि आप सक्षम हैं)। असल में, आपको onDocumentStart और onElement फ़ंक्शंस में XML से आपकी सारी जानकारी मिल जाएगी और जब आप अंत तक पहुंच जाएंगे (यानी onDocumentEnd) आप पार्स की गई जानकारी के आधार पर एक प्रतिक्रिया भेजेंगे। साथ ही, सुनिश्चित करें कि आप प्रत्येक XML संदेश को पार्स करने के बाद self._initializestream() पर कॉल करें या अन्यथा आपको अपवाद मिलेगा। यह आपके लिए एक अच्छा कंकाल के रूप में काम करना चाहिए।

अपने प्रश्नों के मेरे उत्तर:

  1. पता नहीं है :)
  2. यह बहुत ही उचित है। हालांकि मैं आमतौर पर XmlStream (जो केवल Protocol से विरासत में आता है) को उपclass करता है और फिर नियमित Factory ऑब्जेक्ट का उपयोग करता है।
  3. ट्विस्टेड (आपके लिए +1) का उपयोग करते समय चिंता करना एक अच्छी बात है। ऊपर दिए गए दृष्टिकोण का उपयोग करके, आप कॉलबैक/इरबैक को आग लग सकते हैं क्योंकि आप किसी तत्व को पार्स करते हैं और हिट करते हैं या एक्सएमएल के अंत तक पहुंचने तक प्रतीक्षा करते हैं, फिर अपने कॉलबैक को अपने दिल की इच्छा में आग लगाना। मुझे आशा है कि यह समझ में आता है:/
  4. मैंने यह भी वास्तव में सोचा है। मुझे लगता है कि इसमें XmlStream ऑब्जेक्ट (जैसे जैबर और आईआरसी) का उपयोग करने वाले अनुप्रयोगों और प्रोटोकॉल के साथ कुछ करना है। बस onDocumentEnd अधिभारित करें और इसे वह करें जो आप करना चाहते हैं। यह ओओपी की सुंदरता है।

संदर्भ:

पुनश्च

आपकी समस्या (बहुत आम और हल करने के लिए बहुत आसान है, कम से कम में पूछा है मेरी राय) तो इवेंट डिप्चर मॉडल सीखने की कोशिश कर खुद को मत मारो। असल में ऐसा लगता है कि आपके पास कॉलबैक और इरबैक (उर्फ Deferred) पर एक अच्छा संभाल है, इसलिए मेरा सुझाव है कि आप उन लोगों के साथ रहें और प्रेषक से बचें।

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