Por que o fsockopen tem problemas de desempenho e não fope ao enviar uma solicitação de postagem no PHP?

StackOverflow https://stackoverflow.com/questions/1930074

Pergunta

Eu tentei duas implementações diferentes para simular a publicação de um formulário. Um usa fsockopen (Exemplo aqui: http://www.faqts.com/knowledge_base/view.phtml/aid/7962) e o outro usa fopen (Exemplo aqui: http://netevil.org/blog/2006/nov/httppos-from-php-without-curl).

Eu encontrei alguns problemas sérios de desempenho com fsockopen - Quando eu pulo com um depurador, tudo parece funcionar muito bem, mas quando não anexo o depurador, a página leva um tempo para carregar (provavelmente mais de 10 segundos). fopen Funciona perfeitamente (além disso, não preciso analisar os cabeçalhos de resposta). Alguem sabe por quê fsockopen teria esses problemas de desempenho? Tem a ver com a configuração de tempo limite?

Incluí meu código abaixo.


//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);
        }
    }
}

Foi útil?

Solução

Conexões HTTP 1.1 Padrão para persistir. Isso significa que a conexão não é fechada automaticamente e feof() não retorna true até que o pedido de solicitação sai. Para contornar isso, envie o Connection: close Cabeçalho ou use HTTP 1.0, que não suporta conexões persistentes.

Outras dicas

Alguém sabe por que o fsockopen teria esses problemas de desempenho? Tem a ver com a configuração de tempo limite?

Eu tive problemas no passado com o Fsockopen sobre o SSL - mas não é isso que você está pedindo.

Você já tentou usar a família de funções curl_*, isso pode ajudar?

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top