PHP で POST リクエストを送信するときに、fsockopen ではパフォーマンスの問題が発生し、fopen では問題が発生しないのはなぜですか?
-
20-09-2019 - |
質問
フォームの POST をシミュレートするために 2 つの異なる実装を試しました。1つは使用します fsockopen
(ここでの例: http://www.faqts.com/knowledge_base/view.phtml/aid/7962) およびその他の用途 fopen
(ここでの例: http://netevil.org/blog/2006/nov/http-post-from-php-without-curl).
重大なパフォーマンスの問題に遭遇しました fsockopen
- デバッガーを使用してステップ実行すると、すべてが正常に動作しているように見えますが、デバッガーをアタッチしないと、ページの読み込みに非常に時間がかかります (おそらく 10 秒以上)。 fopen
完璧に動作します(さらに、応答ヘッダーを解析する必要はありません)。理由を知っている人はいますか fsockopen
このようなパフォーマンス上の問題が発生するでしょうか?タイムアウト設定とか関係あるのでしょうか?
以下に私のコードを記載しました。
//fsockopen implementation
/**
* The class that posts form data to a specified URL.
* @package Core
* @subpackage Classes
*/
class SU_form_poster_class
{
/**
* The file handle which is created when a form is posted.
* @var resource
*/
protected $file_handle;
protected $port;
protected $timeout;
/**
* Creates a new instance of this class.
* @param int $timeout the timeout (in seconds) to wait for the request
* @param int $port the port to make the request on
*/
public function __construct($timeout = 30, $port = 80)
{
$this->timeout = $timeout;
$this->port = $port;
}
/**
* Sends a POST request to a specified page on a specified host with the
* specified data.
* @param string $path the part of the URL that specifies the page (including
* the query string)
* @param string $host the host part of the URL to post to
* @param string $request_data the data to be posted in "query string" format,
* e.g. name1=value1&name2=value2&name3=value3
*/
public function do_post($path, $host, $request_data)
{
$err_num = 0;
$err_str = '';
$this->file_handle = fsockopen($host, $this->port, $err_num, $err_str, $this->timeout);
if (!$this->file_handle)
{
throw new RuntimeException($err_str, $err_num);
}
else
{
$request = 'POST '.$path." HTTP/1.1\r\n".
'Host: '.$host."\r\n".
"Content-type: application/x-www-form-urlencoded\r\n".
'Content-length: '.strlen($request_data)."\r\n\r\n".
$request_data;
fputs($this->file_handle, $request);
}
}
/**
* Retrieves data from the most recent request.
* @return string the response
*/
public function get_last_response()
{
if (!$this->file_handle)
{
throw new RuntimeException('A valid request must be made first.');
}
else
{
$response = '';
$linenum = 0;
while (!feof($this->file_handle))
{
$line = fgets($this->file_handle, 1024);
if ($linenum > 6)
{
$response .= $line;
}
++$linenum;
}
fclose($this->file_handle);
return $response;
}
}
}
/**
* The class that posts form data to a specified URL.
* @package Core
* @subpackage Classes
*/
class SU_form_poster_class
{
/**
* The file handle which is created when a form is posted.
* @var resource
*/
protected $stream;
/**
* Sends a POST request to a specified page on a specified host with the
* specified data.
* @param string $url
* @param string $request_data the data to be posted in "query string" format,
* e.g. name1=value1&name2=value2&name3=value3
*/
public function do_post($url, $request_data)
{
$params = array(
'http' => array(
'method' => 'POST', 'content' => $request_data
)
);
$context = stream_context_create($params);
$this->stream = fopen($url, 'rb', false, $context);
if (!$this->stream)
{
throw new RuntimeException('Stream was not created correctly');
}
}
/**
* Retrieves data from the most recent request.
* @return string the response
*/
public function get_last_response()
{
if (!$this->stream)
{
throw new RuntimeException('A valid request must be made first.');
}
else
{
return stream_get_contents($this->stream);
}
}
}
解決
HTTP 1.1 接続はデフォルトで永続的です。これは、接続が自動的に閉じられないことを意味します。 feof()
リクエストがタイムアウトするまで true を返しません。これを回避するには、 Connection: close
ヘッダーを使用するか、永続的な接続をサポートしていない HTTP 1.0 を使用します。
他のヒント
誰もがすぐにわかるが、なぜ知っています これらのパフォーマンスの問題がありますか?い それはタイムアウトとしなければなりません 設定?
私は、SSL経由ですぐにわかると、過去に問題を持っていた - それはどのようなあなたの提示ではありません。
。あなたは助けるかもしれない、代わりの機能のcurl_ *ファミリを使用してみましたか?