まず、マニュアルで fsockopen 関数がどのように定義されているかを見てみましょう。
fsockopen — ネットワーク接続または Unix ソケット接続を開きます。
リソース fsockopen ( string $hostname [, int $port = -1 [, int &$errno [, string &$errstr [, float $timeout = ini_get("default_socket_timeout") ]]]]
fsockopen を使用するこのメソッドの本質と CURL メソッドの使用は HTTP プロトコルをシミュレートすることなので、HTTP プロトコルの構築方法に焦点を当てます
注: この関数の機能を使用するには、PHP でallow_url_open をオンにする必要があります。 .ini ファイル
//打开连接通道$fp=fsockopen('www.cnblogs.com',80,$errno,$errstr,30);if(!$fp){ die('连接错误'.$errstr);}set_time_limit(0);//通道打开,模拟HTTP请求,http协议标准的换行是\r\n$http="GET / HTTP/1.1\r\n";$http.="Host: www.cnblogs.com\r\n";$http.="User-Agent: $_SERVER[HTTP_USER_AGENT]\r\n";$http.="Connection: Close\r\n\r\n";//http模拟完成,发送给服务器fwrite($fp,$http);//接受服务器的返回结果$out='';while(!feof($fp)){ $out.=fread($fp,1024);}echo $out;fclose($fp);
開発プロセス中に、ブラウザーをシミュレートしてインターフェイスにアクセスし、戻りデータを取得するという要件に遭遇することがよくあります。最も一般的に使用される方法は、fsockopen を介してインターフェイスとの接続を確立し、命令を実行し、fgets を通じて戻り値を受け取ります
しかし、PHP でシミュレートされたアクセス インターフェイスは、同じインターフェイスにアクセスするブラウザよりもはるかに遅いことがよくあります。この問題は私を長い間悩ませてきましたが、ついにその理由がわかりました。インターネット上の多くの友人が同じ問題を抱えているのを見たので、参考のために共有します
私たちはよく次のように書きます:
1 | while(!feof($sHnd)) { |
2 | $line = fgets($sHnd, 4096); |
} |
遅さの理由が理解できれば、解決策がわかります。
サーバーから返された HTTP ヘッダーには、コンテンツの長さ属性が含まれており、受け入れられたコンテンツの長さがそれと等しい場合、インターフェイスのコンテンツが次のようになっていると結論付けることができます。取得済みですので、もう待つ必要はありません。具体的な方法は、コンテンツが残りの合計長 (min(4096,$leftlength)) を超えないたびに実行されます。残りの合計長が 0 になった場合、while(feof($xxxxx)) ループから抜けます。
このような修正の後、PHP のソケットを介したインターフェイスへのアクセスが遅いという問題は基本的に解決されましたが、速度の最適化を続けるという考えはまだ KeepAlive にあります。
インターフェースへのアクセスにかかる時間のかなりの部分が接続の確立に費やされることは誰もが知っていますが、インターフェースを頻繁に呼び出す必要がある場合には、最適化の余地がまだたくさんあります。サーバーが接続を維持しているので、PHPも接続を保存していれば、接続を確立する必要はないということでしょうか?答えは「はい」です。初めてインターフェイスにアクセスするときは、pfsockopen (pfsockopen と fsockopen の唯一の違いは、長い接続を確立することです) 関数を使用してサーバーとの接続を確立し、インターフェイスを閉じ (fclose) しないでください。アクセスが完了したら、この接続を直接使用してください。具体的にはコード内で次のようになります。まず接続があるかどうかを確認し、接続がある場合は引き続き使用し、ない場合は pfsockopen 接続を確立します。
さらに、インターフェイスによって返されるコンテンツが比較的短い場合 (たとえば、50 文字未満)、HTTP リクエスト ヘッダーの Accept-Encoding の gzip を削除するなど、最適化の余地がまだあります。その機能は、サーバーが gzip をサポートしている場合、圧縮されたコンテンツを受け入れることができることをサーバーに通知し、ブラウザはコンテンツを取得した後に解凍して表示します。ただし、コンテンツが短すぎる場合は、圧縮と解凍の時間を考慮すると、圧縮後のボリュームが増加し、損失が大きくなります。
上記の手順の後、アクセス インターフェイスの速度はブラウザの速度と同じになり、理論的には少し速くなります。