Почему fsockopen имеет проблемы с производительностью и не открывается при отправке запроса POST в PHP?
Я пробовал две разные реализации для моделирования POSTing формы. Один использует 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);
}
}
}
2 ответа
Соединения HTTP 1.1 по умолчанию постоянны. Это означает, что соединение не закрывается автоматически и feof()
не возвращает истину, пока не истечет время ожидания запроса. Чтобы обойти это, отправьте Connection: close
заголовок или используйте HTTP 1.0, который не поддерживает постоянные соединения.
Кто-нибудь знает, почему fsockopen будет иметь эти проблемы с производительностью? Это связано с настройкой тайм-аута?
В прошлом у меня были проблемы с fsockopen поверх ssl - но это не то, что вы просите.
Вы пытались использовать семейство функций curl_*, это может помочь?