PHP

2015-09-04 5 views
12

के साथ एक लाइव SOAP डेटा स्ट्रीम का विश्लेषण करना मेरे पास एक एंटरप्राइज़ एप्लिकेशन है जो डेटा एकत्र करने के लिए एक काफी मजबूत API प्रदान करता है। वर्तमान में मैं प्रत्येक उपयोगकर्ता से पूछताछ कर रहा हूं कि मैं हर सेकेंड में एक लूप में एक अपडेट चाहता हूं। हालांकि नया एपीआई दस्तावेज अब सभी उपयोगकर्ताओं पर सभी बदलावों की लाइव स्ट्रीम प्रदान करता है। मैं सोच रहा हूं कि मैं इस लाइव डेटा को कैसे पार्स कर सकता हूं क्योंकि यह php के साथ आता है। यहाँ कुछ विवरण हैं:PHP

डेटा एक सोप अनुरोध के माध्यम से अनुरोध किया गया है, और मैं PHP का उपयोग कर रहा इस तरह इन अनुरोध करने के लिए (एक अनन्य आईडी से सत्र दीक्षा का उदाहरण लौटे):

//Get a session ID for this user for the shoretel WEBAPI 
$soap_url = 'http://11.11.11.11:8070/ShoreTelWebSDK?wsdl'; 
$client = new SOAPClient($soap_url, array('proxy_host' => '11.11.11.11', 'proxy_port' => 8070, 'trace' => 1)); 
$client = new SoapClient($soap_url); 

$header = new SoapHeader('http://www.ShoreTel.com/ProServices/SDK/Web'); 
$client->__setSoapHeaders($header); 
$registered_string = $client->RegisterClient(array(
       'clientName' => '11.11.11.211' 
      )); 
$registered_string = get_object_vars($registered_string); 
$session = $registered_string['RegisterClientResult']; 

नई विधि मुझे एक समय अवधि निर्दिष्ट करने की अनुमति देता है। उदाहरण के लिए यदि मैं सभी घटनाओं को 1 मिनट के लिए प्राप्त करना चाहता हूं तो कॉल शुरू हो जाएगा, एक मिनट प्रतीक्षा करें, फिर उस मिनट के दौरान होने वाली सभी घटनाओं को वापस कर दें।

मैं जो करना चाहता हूं वह हर घटना को पकड़ लेता है, और इसे डेटाबेस में डालें। क्या यह कुछ है जो मैं PHP के साथ पूरा कर सकता हूं, या ऐसा करने के लिए मुझे दूसरी भाषा देखने की ज़रूरत है?

उत्तर

2

ठीक है, लक्ष्य "टाइमआउट" और/या "अंतराल" में "एसओएपी रिपॉन्स स्ट्रीम" करना है?

मैं SoapClient __doRequest() विधि को ओवरराइड करने और fsockopen() के माध्यम से एक कस्टम कनेक्शन लागू करने का सुझाव देता हूं और stream_get_contents() के साथ डेटा स्ट्रीम करता हूं। अब आपको एक्सएमएल डेटा की स्ट्रीम मिलती है और आप जो चाहते हैं उसके बीच में है। आपको आंतरिक लिंक्स लाने के लिए शायद XML लिफाफा या इसके कुछ हिस्सों को निकालना होगा, शायद स्ट्रिंग फ़ंक्शंस का उपयोग करना या preg_match का उपयोग करके।

निम्न कोड एक SoapClientTimeout क्लास प्रदान करता है, जहां टाइमआउट stream_set_timeout() के माध्यम से सेट किया जाता है। यह उपयोग-मामले के लिए है, जब सर्वर में धीमी प्रतिक्रिया होती है और आप यह सुनिश्चित करना चाहते हैं कि कब सुनना समाप्त हो जाए।

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

$timeout = 60; // seconds 
stream_set_blocking($socket, true); 
stream_set_timeout($socket, $timeout); 

आप एक धारा है, जो ब्लॉक, 1 मिनट के बाद और बंद कर देता है आप एक पाश की जरूरत है जब (के साथ एक ठोस निकास की स्थिति) अगले अनुरोध को ट्रिगर कर रहा है।


class SoapClientTimeout extends SoapClient 
{  
    public function __construct ($wsdl, $options = null) 
    { 
     if (!$options) $options = []; 

     $this->_connectionTimeout = @$options['connection_timeout'] ?: ini_get ('default_socket_timeout'); 
     $this->_socketTimeout = @$options['socket_timeout'] ?: ini_get ('default_socket_timeout'); 
     unset ($options['socket_timeout']); 

     parent::__construct($wsdl, $options); 
    } 

    /** 
    * Override parent __doRequest and add "timeout" functionality. 
    */ 
    public function __doRequest ($request, $location, $action, $version, $one_way = 0) 
    { 
     // fetch host, port, and scheme from url. 
     $url_parts = parse_url($location); 

     $host = $url_parts['host']; 
     $port = @$url_parts['port'] ?: ($url_parts['scheme'] == 'https' ? 443 : 80); 
     $length = strlen ($request); 

     // create HTTP SOAP request. 
     $http_req = "POST $location HTTP/1.0\r\n"; 
     $http_req .= "Host: $host\r\n"; 
     $http_req .= "SoapAction: $action\r\n"; 
     $http_req .= "Content-Type: text/xml; charset=utf-8\r\n"; 
     $http_req .= "Content-Length: $length\r\n"; 
     $http_req .= "\r\n"; 
     $http_req .= $request; 

     // switch to SSL, when requested 
     if ($url_parts['scheme'] == 'https') $host = 'ssl://'.$host; 

     // connect 
     $socket = @fsockopen($host, $port, $errno, $errstr, $this->_connectionTimeout); 

     if (!$socket) { 
      throw new SoapFault('Client',"Failed to connect to SOAP server ($location): $errstr"); 
     } 

     // send request with socket timeout 
     stream_set_timeout($socket, $this->_socketTimeout); 
     fwrite ($socket, $http_req); 

     // start reading the response. 
     $http_response = stream_get_contents($socket); 

     // close the socket and throw an exception if we timed out. 
     $info = stream_get_meta_data($socket); 
     fclose ($socket); 
     if ($info['timed_out']) { 
      throw new SoapFault ('Client', "HTTP timeout contacting $location"); 
     } 

     // the stream contains XML data 
     // lets extract the XML from the HTTP response and return it. 
     $response = preg_replace (
      '/ 
       \A  # Start of string 
       .*?  # Match any number of characters (as few as possible) 
       ^  # Start of line 
       \r  # Carriage Return 
       $  # End of line 
      /smx', 
      '', $http_response 
     ); 
     return $response; 
    } 

} 
0

बाइंड सॉकेट

समारोह बाँध एक विशेष पते और बंदरगाह के लिए एक सॉकेट बाध्य करने के लिए इस्तेमाल किया जा सकता। कनेक्ट फ़ंक्शन के समान इसे एक sockaddr_in संरचना की आवश्यकता है।

त्वरित उदाहरण

if(!($sock = socket_create(AF_INET, SOCK_STREAM, 0))) 
{ 
    $errorcode = socket_last_error(); 
    $errormsg = socket_strerror($errorcode); 

    die("Couldn't create socket: [$errorcode] $errormsg \n"); 
} 

echo "Socket created \n"; 

// Bind the source address 
if(!socket_bind($sock, "127.0.0.1" , 5000)) 
{ 
    $errorcode = socket_last_error(); 
    $errormsg = socket_strerror($errorcode); 

    die("Could not bind socket : [$errorcode] $errormsg \n"); 
} 

echo "Socket bind OK \n"; 

अब जब कि बाँध किया जाता है, सॉकेट बनाने के लिए अपने समय के कनेक्शन के लिए सुनो। हम किसी विशेष आईपी पते और एक निश्चित पोर्ट नंबर पर सॉकेट बांधते हैं। ऐसा करके हम यह सुनिश्चित करते हैं कि इस पोर्ट नंबर की ओर निर्देशित सभी आने वाले डेटा इस एप्लिकेशन द्वारा प्राप्त किए जाएंगे।

इससे यह स्पष्ट हो जाता है कि आपके पास एक ही बंदरगाह से 2 सॉकेट बाध्य नहीं हो सकते हैं। इस नियम के अपवाद हैं लेकिन हम इसे किसी अन्य लेख में देखेंगे।

कनेक्शन

एक बंदरगाह अगली बात हम क्या करने की जरूरत कनेक्शन के लिए सुन रहा है करने के लिए एक सॉकेट बंधन के बाद के लिए सुनो। इसके लिए हमें सॉकेट को सुनने के मोड में रखना होगा। फंक्शन socket_listen सॉकेट को सुनने मोड में रखने के लिए प्रयोग किया जाता है। बांधने के बाद बस निम्नलिखित पंक्ति जोड़ें।

//listen 
socket_listen ($sock , 10) 

फ़ंक्शन socket_listen का दूसरा पैरामीटर बैकलॉग कहा जाता है। यह आने वाले कनेक्शनों की संख्या को नियंत्रित करता है जिन्हें "प्रतीक्षा" रखा जाता है यदि प्रोग्राम पहले से व्यस्त है। तो 10 निर्दिष्ट करके, इसका मतलब है कि यदि 10 कनेक्शन पहले ही संसाधित होने की प्रतीक्षा कर रहे हैं, तो 11 वें कनेक्शन अनुरोध को खारिज कर दिया जाएगा। Socket_accept की जांच के बाद यह अधिक स्पष्ट होगा।

अब नए कनेक्शन को स्वीकार करने का मुख्य हिस्सा आता है।

स्वीकार कनेक्शन

समारोह socket_accept इस के लिए प्रयोग किया जाता है।

if(!($sock = socket_create(AF_INET, SOCK_STREAM, 0))) 
{ 
    $errorcode = socket_last_error(); 
    $errormsg = socket_strerror($errorcode); 

    die("Couldn't create socket: [$errorcode] $errormsg \n"); 
} 

echo "Socket created \n"; 

// Bind the source address 
if(!socket_bind($sock, "127.0.0.1" , 5000)) 
{ 
    $errorcode = socket_last_error(); 
    $errormsg = socket_strerror($errorcode); 

    die("Could not bind socket : [$errorcode] $errormsg \n"); 
} 

echo "Socket bind OK \n"; 

if(!socket_listen ($sock , 10)) 
{ 
    $errorcode = socket_last_error(); 
    $errormsg = socket_strerror($errorcode); 

    die("Could not listen on socket : [$errorcode] $errormsg \n"); 
} 

echo "Socket listen OK \n"; 

echo "Waiting for incoming connections... \n"; 

//Accept incoming connection - This is a blocking call 
$client = socket_accept($sock); 

//display information about the client who is connected 
if(socket_getpeername($client , $address , $port)) 
{ 
    echo "Client $address : $port is now connected to us."; 
} 

socket_close($client); 
socket_close($sock); 

आउटपुट

कार्यक्रम चलाएं। यह $ php /var/www/server.php सॉकेट बनाया सॉकेट ठीक सॉकेट सुनने ठीक इनकमिंग कनेक्शन के लिए प्रतीक्षा कर बाँध ...

तो अब इस कार्यक्रम के बंदरगाह 5000 पर इनकमिंग कनेक्शन के लिए प्रतीक्षा कर रहा है दिखाना चाहिए। इस कार्यक्रम को बंद न करें, इसे चलते रहें। अब ग्राहक इस पोर्ट पर उससे जुड़ सकता है। हम परीक्षण के लिए टेलनेट क्लाइंट का उपयोग करेंगे। टर्मिनल खोलें और यह तुरंत $ टेलनेट स्थानीय होस्ट 5000 कोशिश कर रहा 127.0.0.1 ... स्थानीय होस्ट से कनेक्ट किया गया दिखाएगा टाइप $ टेलनेट स्थानीय होस्ट 5000

। एस्केप कैरेक्टर '^]' है। कनेक्शन विदेशी मेजबान द्वारा बंद कर दिया गया।

और सर्वर आउटपुट क्लाइंट 127.0.0.1: 36689 अब हमारे साथ कनेक्ट होगा।

तो हम देख सकते हैं कि क्लाइंट सर्वर से जुड़ा हुआ है। उपर्युक्त चरणों का प्रयास करें जब तक कि आप इसे सही काम नहीं कर लेते।

नोट

socket_getpeername समारोह ग्राहक जो एक विशेष सॉकेट के माध्यम से सर्वर से कनेक्ट है के बारे में जानकारी प्राप्त करने के लिए प्रयोग किया जाता है।

+0

कैसे यह मेरे सोप कॉल की लाइव सामग्री प्राप्त करने में मदद मिलेगी? –

+0

इस पर बेहतर स्पष्टीकरण के लिए आप PHP संदर्भ का पालन कर सकते हैं। http://php.net/manual/en/function.http-get-request-body.php –

+0

@NavnishBardwaj आपके द्वारा पोस्ट किया गया कोड "टाइमआउट" और/या में "एसओएपी रिपॉन्स स्ट्रीमिंग" से कैसे संबंधित है "मध्यान्तर"? जो मैं अब देखता हूं वह समस्या का समाधान नहीं करता है और केवल प्रश्न का उत्तर नहीं है। कृपया बताएं कि समस्या के लिए आपका कोड उपयोगी क्यों है। –

0

मैं थोड़ी परेशान हूं: SOAP (सरल ऑब्जेक्ट एक्सेस प्रोटोकॉल होने के नाते) लाइव स्ट्रीमिंग के बिल्कुल विपरीत है। प्रत्येक एसओएपी संदेश पूरी तरह से encapsulated है: यह शुरुआत और अंत है। यह बस स्ट्रीम नहीं किया जा सकता है।

आपने कुछ "नई विधि" का उल्लेख किया है लेकिन आप कोई विवरण देने में विफल रहे। "लाइव" अपडेट दोहराए गए अनुरोधों से प्राप्त किए जा सकते हैं या यह वास्तविक डेटा स्ट्रीम हो सकता है। यदि यह पूर्व है: आप एसओएपी से दूर हो सकते हैं लेकिन हर सेकेंड एसओएपी को कॉल करना वास्तव में अच्छा विचार नहीं है: रिमोट सर्वर एडमिन इस तरह के हमले से खुश नहीं होगा। यदि यह बाद वाला है: यह SOAP नहीं हो सकता है। अवधि।

जब तक आप यह स्पष्ट नहीं करते कि "नई विधि" क्या करती है और इसे कैसे लागू किया जाता है, कोई भी आपको यह बताने में सक्षम नहीं होगा कि आपकी समस्या का समाधान कैसे करें। लेकिन बाकी दिनों में PHP को आश्वासन दिया है कि काफी कुछ भी सक्षम है। तो यदि आप PHP के साथ सहज हैं तो निश्चित रूप से आपको जो भी समस्या आती है, उसे निश्चित रूप से कुछ अन्य प्रोग्रामिंग भाषा में बदलने की आवश्यकता नहीं है। मेरा सुझाव है कि आप अपना मूल प्रश्न संशोधित करें और प्रासंगिक विवरण जोड़ें। मुझे यकीन है कि आपको यहां बहुत सारे लोग मिलेंगे जो आपको सटीक समाधान देने में सक्षम होंगे।

0

आपके कोड के साथ कुछ बातें:

  1. आप $ ग्राहक दो बार का दृष्टांत, इसलिए पहले $ ग्राहक को प्रभावी ढंग से ओवरराइट है।
  2. आपके SOAP शीर्षलेख में केवल नामस्थान तर्क है। इसकी आवश्यकता नहीं हो सकती है।

आपका कोड केवल एक सत्र आईडी पंजीकृत करने के लिए प्रतीत होता है। यह स्पष्ट नहीं है कि डेटा कहां है, शायद $ register_string सरणी के किसी अन्य तत्व में? मुझे संदेह है कि इसके बाद आपको लिखने के लिए और कोड चाहिए।

आमतौर पर, मेरे अनुभव में, आप यूआरएल बनाने के लिए लौटा सत्र आईडी का उपयोग करेंगे। फिर आप डेटा स्ट्रीम तक पहुंचने के लिए उस यूआरएल का उपयोग करेंगे। यह नहीं एक एसओएपी कॉल हो सकता है, लेकिन आप जो भी तरीका पसंद करते हैं उसका उपयोग कर एक सामान्य वेब अनुरोध (उदा। file_get_contents('http://example.com/blah?session=[SESSIONID]'))। सर्वर डेटा लौटने से पहले आपको प्रमाणीकृत करने के लिए सत्र आईडी का उपयोग करेगा।

यदि यह इस तरह काम करता है, तो उत्तर हाँ है, आप डेटा तक पहुंच सकते हैं और इसे डेटाबेस में डाल सकते हैं, लेकिन केवल सत्र आईडी मान्य होने पर ही। जब सत्र आईडी समाप्त हो जाती है, तो आपको RegisterClient() को फिर से कॉल करना होगा। इससे कोई फर्क नहीं पड़ता कि आप किस भाषा का उपयोग करते हैं।

0

सरल तरीका आपके PHP साबुन फ़ाइल में टाइमआउट के साथ websockets या यहां तक ​​कि aync AJAX अनुरोध का उपयोग करने का आसान तरीका हो सकता है।

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