2015-09-04 14 views
12

私はデータを収集するためのかなり堅牢なAPIを提供するエンタープライズアプリケーションを持っています。現在、私はループごとに1秒ごとに更新したいと思っている各ユーザーに問い合わせています。ただし、新しいAPIドキュメントでは、すべてのユーザーのすべての変更のライブストリームが提供されるようになりました。私はPHPで提供されるので、このライブデータをどのように解析できるのだろうかと思います。ここではいくつかの詳細は以下のとおりです。PHPでライブSOAPデータストリームを解析する

データは、SOAPリクエストを介して要求されており、私はこのようなこれらの要求をするためにPHPを使用しています(ユニークなIDを持つセッション開始の例は、返された):

//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分間取得したい場合は、コールが開始され、1分待ってから、その分に発生したすべてのイベントを返します。

私がしたいことは、発生した各イベントをつかみ、それをデータベースに挿入することです。これは私がPHPで達成できるものか、これを実現するために別の言語を探す必要がありますか?

答えて

2

[OK]の目的は、「タイムアウト」および/または「間隔」を使用して「SOAP応答をストリーミングする」ことですか?

SoapClient __doRequest()メソッドをオーバーライドし、fsockopen()でカスタム接続を実装し、stream_get_contents()でデータをストリームすることをお勧めします。 これで、XMLデータのストリームが得られました。途中でXMLデータを取得できます。 おそらく文字列関数を使用するか、preg_matchを使用して内部コンテンツを取得するなどして、XMLエンベロープまたはその一部を抽出する必要があります。

次のコードは、タイムアウトがstream_set_timeout()で設定されるSoapClientTimeoutクラスを提供します。これは、サーバーの応答が遅く、リッスンを終了するタイミングを確認したい場合に使用します。

私はそれを試してみて、ソケットのタイムアウト動作を調整することをお勧めします。 あなたがしたいのは、しばらくしてからリスニングを止めることです(インターバルフェッチ)。 それで、あなたはしばらくの後、ストリームからの読み込みを停止し、ブロッキングタイムアウトを結合しようとするクラウド:

$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

バインドソケット

機能バインドは、特定のアドレスとポートにソケットをバインドするために使用することができます。 connect関数に似た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"; 

、ソケットを作るためにその時間は接続に耳を傾けます。特定のIPアドレスと特定のポート番号にソケットをバインドします。これにより、このポート番号に向けられたすべての着信データがこのアプリケーションによって確実に受信されるようになります。

これは、2つのソケットを同じポートにバインドすることができないことを明白にしています。この規則には例外がありますが、他のいくつかの記事ではそれを調べます。

は、私たちが行う必要があり、次のものが接続を待ち受けるあるポートにソケットをバインドした後に接続

の音を聞きます。このためには、ソケットをリスニングモードにする必要があります。機能socket_listenは、ソケットをリスニングモードにするために使用されます。 bindの後に次の行を追加するだけです。

socket_listen関数の2番目のパラメータは、バックログと呼ばれます。これは、プログラムがすでにビジー状態の場合に「待機中」に保たれる着信接続の数を制御します。したがって、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); 

出力

プログラムを実行します。それは ソケットは、ソケットがOK ソケットが着信接続を待機OK を聞くバインド を作成/var/www/server.php $ phpの...

はだから今、このプログラムは、ポート5000上の着信接続を待っているが表示されるはずです。このプログラムを閉じず、実行してください。 クライアントはこのポートで接続できます。これをテストするためにtelnetクライアントを使用します。それはすぐにlocalhostに接続され の$のtelnet localhostの5000 しようと127.0.0.1 ... が表示されますターミナルを開き、 の$のtelnet localhostの5000

を入力します。 エスケープ文字は '^]'です。 外部ホストによって接続が閉じられました。

とサーバーの出力は クライアント127.0.0.1が表示されます:36689は、今私たちに接続されています。

これで、クライアントがサーバーに接続していることがわかります。あなたが完璧に働くまで、上記の手順を試してみてください。

socket_getpeername機能は、特定のソケットを介してサーバに接続しているクライアントに関する詳細情報を取得するために使用されます。

+0

これはどのように私は、SOAPコールのライブ内容を得るのを助けますか? –

+0

これについてより明確にするために、PHPのリファレンスに従うことができます。 http://php.net/manual/en/function.http-get-request-body.php –

+0

@NavnishBhardwajあなたが投稿したコードは、「タイムアウト」を伴う「SOAP応答のストリーミング」および/または"間隔"?私が今見ているのは問題を解決するものではなく、単にその質問に対する答えではありません。なぜあなたのコードが問題に役立つのかを説明してください。 –

0

私は少し困惑しています:SOAP(シンプルオブジェクトアクセスプロトコルであること)がライブストリーミングとは全く逆です。すべてのSOAPメッセージは完全にカプセル化されています。開始と終了があります。それは単にストリームすることはできません。

"新しい方法"について言及しましたが、詳細を教えていませんでした。 「ライブ」更新は、繰り返し要求によって達成されてもよく、または実際のデータストリームであってもよい。前者の場合は、SOAPを使用することができますが、毎秒SOAPを呼び出すことは本当に良い考えではありません。リモートサーバーの管理者は、このような攻撃に満足できません。後者の場合:SOAPにすることはできません。期間。

あなたは「新しい方法」はありませんし、それが呼び出されたか、誰がどのようにあなたの問題を解決するためにあなたを伝えることはできないだろうか明らかにする場合を除き。しかし、安心してPHPを使うことができます。 PHPに慣れていれば、どんな問題に直面しても、他のプログラミング言語に変更する必要はありません。元の質問を修正し、関連する詳細を追加することをお勧めします。私はあなたが正確な解決策を与えることができるだろうここにたくさんの人々を見つけることを確信しています。

0

あなたのコードを持つカップルの事:

  1. あなたが二回$クライアントをインスタンス化し、その最初の$クライアントが効果的に上書きされます。
  2. SOAPヘッダーには名前空間の引数のみがあります。それは必須ではないかもしれません。

あなたのコードはセッションIDのみを登録しているようです。データがどこにあるのかは分かりませんが、おそらく$ registered_string配列の別の要素にありますか?私はあなたがこの後に書く必要があるより多くのコードがあると思う。

通常、私の経験では、返されたセッションIDを使用してURLを構築します。そのURLを使用してデータストリームにアクセスします。これはで、はSOAP呼び出しですが、好きな方法(例:file_get_contents('http://example.com/blah?session=[SESSIONID]'))を使用した通常のウェブリクエストです。サーバーはセッションIDを使用して、データを返す前にユーザーを認証します。

これが正常に動作している場合、答えは「はい」です。データにアクセスしてデータベースに挿入できますが、セッションIDが有効な場合のみです。セッションIDが期限切れになったら、RegisterClient()をもう一度呼び出す必要があります。これはあなたがどの言語を使用していても当てはまります。

0

シンプルな方法は、あなたのPHPソープファイルにタイムアウトを設定してWebソケットや同期Ajaxリクエストを使用することができます。