fsockopenは時間がかかる?
不思議?というか、わからない現象に出くわして、ちょっと悩んでいる。
外部URLに接続してコンテンツを持ってくる(要はRESTでxmlを取得したりする)時には、いろいろな取得方法がある。
(1) fopenとかfile_get_contentsで取得
引数にURLを直接渡す方法で一番簡単だが、データを取りこぼすことがある。
(2) curlで取得
インストール時のコンパイルオプションによっては使えないことがある。
(3) fsockopenで直接HTTPを話して取得
直接HTTPを話すスクリプトを用意する必要がある。
PEARのHTTP_Requestを使うという選択肢もあるが、これも結局は内部で上記を呼び出している(と思う)ので同じことだ。
上記で一番確実な方法は(3)のfsockopenを使う方法だ。PHPの標準関数でできるし、取りこぼしもないので、これを使うべきだ(と思う)。しかし、ちょっと困ったことになってしまった。fsockopenでデータを取得するのに時間がかかるのだ。
fsockopenの手順としては、以下のような感じ。
(1) fsockopenで相手サーバに接続
(2) fputでリクエストを送信
(3) fgetsでレスポンスを受信
しかし(1)で異常に時間がかかってしまうのだ。時間にして20秒くらいかかる。これがなぜだかわからない・・・。
ちなみに当該URLを、ブラウザ上で開くと数秒で表示される。それにfile_get_contentsで取得しても、やはり数秒で結果を返してくる。
ん〜〜〜。
いろいろ調べてみたが理由がわからなかった。レスポンスを受信するのに時間がかかるのであれば、相手サーバの処理時間とか、通信速度の問題か、とも思うのだが、fsockopenで時間がかかるのが不思議だ。fsockopenで時間がかかるのなら、file_get_contentsでも時間がかかってしまいそうなのだが、あいにくこちらは時間がかからない。
どなたか、思い当たるところがあったら教えていただきたい。
どうぞよろしくお願いします。
2007/08/26 at 1:26 PM
fsockopenでHTTPリクエスト
PHPのテクメモ | fsockopenは時間がかかる? 自分も以前にPHPでHTTPリクエスト投げてあれこれする処理を書いたことがあるけれども、特に時間がかかるというようなことはなかった。 気になったので、部分的にコードを書いてみたけれど、やはり大丈夫なようだ。かおるん
2007/08/27 at 7:24 PM
接続先ホスト名はIPアドレス指定ですか?
2007/08/28 at 12:33 AM
ホスト名は「ホスト名」で指定しています。
DNS絡みの問題?とお考えかもしれないですけど、もしそうならfile_get_contentsでも同様に遅くなる、と思うのですがいかがでしょう。
2007/08/28 at 2:28 PM
勿論、通常であればそうなんですが
一応念のためといいますか(笑)
ちなみにfsockopenで接続に待たされているときの
ソケットの状態はnetstatで確認できますか?
2007/08/29 at 10:19 PM
時間できたら確認してみます♪
2007/09/02 at 7:22 PM
socket_set_timeout関数を使ってタイムアウトを指定するとか、如何でしょう?
2007/09/02 at 8:13 PM
タイムアウト検出して、その後どうするんですか?。
そもそもちゃんと接続できてるわけで、なぜ時間がかかるか調べてるんですけど。
2007/09/03 at 8:10 PM
Connection: Keep-Alive
になっていませんか?
Connection: Close
にしてみてはどうですか?
2007/09/03 at 11:34 PM
「Connectionどうこう」というのはfsockopenで接続した後にHTTPでおしゃべりするときの話ですよね。今回はそういうことではなくて、単純にfsockopenに時間がかかるのです(くどいようですが)。
var_dump(microtime());
$fp=fsockopen(‘webservices.amazon.co.jp’,80,$num,$str,30);
var_dump(microtime());
var_dump($fp);
これだけ。別の環境で動かすと問題ないので、現在の環境でのみ遅くなるようです。いまだ解決に至らず・・・。
2007/09/04 at 8:26 AM
うちは
$sock = socket_create( AF_INET, SOCK_STREAM, SOL_TCP );
socket_connect( $sock, $host, 80 );
socket_write( $sock, $header, strlen( $header ) );
で接続しています。
このときに、上記のヘッダーを云々すると、応答速度が上がりました。
通りすがりさんが言われているタイムアウトの件もそれかと思いコメントしました。
>別の環境で動かすと問題ないので
これが今まで出てこなかったので、すべての環境で重いのかと思いました。
2007/09/04 at 8:45 AM
根本が違うのです。socket_set_timeoutもConnection: Keep-Aliveもソケット接続が出来た後のお話ですよね?。ソケット接続そのものに時間がかかっちゃうわけなんですよ。
fsockopenにバグがあるとか思ってなくて、環境の問題か、オプション指定の問題か・・・、なんて思案しているわけです。
$sock = socket_create( AF_INET, SOCK_STREAM, SOL_TCP );
こういう書き方もあるのですね。感心しました。