2009年2月28日土曜日

fsockopen()でタイムアウト

よくWEBサイトで、広告バナーを広告サーバー(ADサーバー)から取得→表示という事が行われます。

その場合、phpなサイトではfsockopen()を使って、ソケット通信でバナーを取得する事が多いと思うのですがその場合のメモ。

※以下PHPマニュアルより
resource fsockopen ( string $hostname [, int $port [, int &$errno [, string &$errstr [, float $timeout ]]]] )
第5引数の float $timeout はソケット通信時のタイムアウト時間(秒)です。
で!僕はtimeout秒数は、設定した秒数ソケットの応答がなかった場合に接続を断念するものだと思っていました。

いや、そうなんですけど、言葉で説明むずかしいのですが、
1)ソケット接続完了
2)fputs()で情報を取得しに行く
3)応答がない、、、
4)timeout秒だけ頑張る
5)それでも応答がなければ諦める
↑のような動作だと思っていたのです。

調べてみると、実はそうではなくtimeout秒数は、ソケット接続を確立させるために待つ秒数であり、接続完了後に応答がなくて待つ秒数ではないみたいです。(実際そういう現象に遭遇しました、、><)

ソケットは接続確立されたが、ソケット接続先のサーバーから応答がない場合に切断したい場合の処理は

soket_set_timeout()と
stream_get_meta_data()を使え!
array stream_get_meta_data ( resource $stream )
既存の stream に関する情報を取得します。 ストリームは fopen() か、 fsockopen() か、pfsockopen() で 作成されたいずれのものも指定できます。 結果の配列は次のような項目を含みます。

timed_out (bool ) - 最後に fread() または fgets() でデータを待っている時にタイムアウトした場合 TRUE を返します。
この関数は、結果が配列で返ってくるのですがその中の'time_out'がtrueだった場合は応答時間切れのフラグです。

-- 以下サンプル
// ソケットでHOST:PORTに接続(TIMEOUT秒は頑張る)
if ($fp = @fsockopen(HOST, PORT, err_no, err_str, TIMEOUT)) {
  // 接続確立したら、タイムアウトは5秒に設定
  socket_set_timeout($fp, 5);
  // ソケットのメタデータを取得
  $socket_data_arr = stream_get_meta_data($fp);
  // ソケットでデータを送信
  fputs($fp, $hoge);
  // 応答があれば応答を取得
  $buf = "";
  // $socket_data_arr[time_out"]がtrueなら接続タイムアウト!
  while (!feof($fp) && !$socket_data_arr["time_out"]) {
    $buf .= fgets($fp, 1024);
  }
  fclose($fp);
}

以上。・゚・(ノε`)・゚・。

0 件のコメント: