with texto strip_tags remove quitar para limpiar funcion etiquetas ejemplo php http asynchronous

php - texto - strip_tags wordpress



Llamadas PHP asincrónicas? (15)

¿Hay alguna forma en PHP para hacer llamadas http asincrónicas? No me importa la respuesta, solo quiero hacer algo como file_get_contents() , pero no esperar a que termine la solicitud antes de ejecutar el resto de mi código. Esto sería muy útil para desencadenar "eventos" de una clase en mi aplicación o desencadenar procesos largos.

¿Algunas ideas?


Extensión del evento

Event extensión del Event es muy apropiada. Es un puerto de la biblioteca Libevent que está diseñado para eventos de E / S, principalmente para redes.

He escrito un cliente HTTP de muestra que permite programar un número de solicitudes HTTP y ejecutarlas de forma asincrónica.

Esta es una clase de cliente HTTP de muestra basada en la extensión de Event .

La clase permite programar un número de solicitudes HTTP y luego ejecutarlas de forma asíncrona.

http-client.php

<?php class MyHttpClient { /// @var EventBase protected $base; /// @var array Instances of EventHttpConnection protected $connections = []; public function __construct() { $this->base = new EventBase(); } /** * Dispatches all pending requests (events) * * @return void */ public function run() { $this->base->dispatch(); } public function __destruct() { // Destroy connection objects explicitly, don''t wait for GC. // Otherwise, EventBase may be free''d earlier. $this->connections = null; } /** * @brief Adds a pending HTTP request * * @param string $address Hostname, or IP * @param int $port Port number * @param array $headers Extra HTTP headers * @param int $cmd A EventHttpRequest::CMD_* constant * @param string $resource HTTP request resource, e.g. ''/page?a=b&c=d'' * * @return EventHttpRequest|false */ public function addRequest($address, $port, array $headers, $cmd = EventHttpRequest::CMD_GET, $resource = ''/'') { $conn = new EventHttpConnection($this->base, null, $address, $port); $conn->setTimeout(5); $req = new EventHttpRequest([$this, ''_requestHandler''], $this->base); foreach ($headers as $k => $v) { $req->addHeader($k, $v, EventHttpRequest::OUTPUT_HEADER); } $req->addHeader(''Host'', $address, EventHttpRequest::OUTPUT_HEADER); $req->addHeader(''Connection'', ''close'', EventHttpRequest::OUTPUT_HEADER); if ($conn->makeRequest($req, $cmd, $resource)) { $this->connections []= $conn; return $req; } return false; } /** * @brief Handles an HTTP request * * @param EventHttpRequest $req * @param mixed $unused * * @return void */ public function _requestHandler($req, $unused) { if (is_null($req)) { echo "Timed out/n"; } else { $response_code = $req->getResponseCode(); if ($response_code == 0) { echo "Connection refused/n"; } elseif ($response_code != 200) { echo "Unexpected response: $response_code/n"; } else { echo "Success: $response_code/n"; $buf = $req->getInputBuffer(); echo "Body:/n"; while ($s = $buf->readLine(EventBuffer::EOL_ANY)) { echo $s, PHP_EOL; } } } } } $address = "my-host.local"; $port = 80; $headers = [ ''User-Agent'' => ''My-User-Agent/1.0'', ]; $client = new MyHttpClient(); // Add pending requests for ($i = 0; $i < 10; $i++) { $client->addRequest($address, $port, $headers, EventHttpRequest::CMD_GET, ''/test.php?a='' . $i); } // Dispatch pending requests $client->run();

test.php

Este es un script de muestra en el lado del servidor.

<?php echo ''GET: '', var_export($_GET, true), PHP_EOL; echo ''User-Agent: '', $_SERVER[''HTTP_USER_AGENT''] ?? ''(none)'', PHP_EOL;

Uso

php http-client.php

Muestra de salida

Success: 200 Body: GET: array ( ''a'' => ''1'', ) User-Agent: My-User-Agent/1.0 Success: 200 Body: GET: array ( ''a'' => ''0'', ) User-Agent: My-User-Agent/1.0 Success: 200 Body: GET: array ( ''a'' => ''3'', ) ...

(Recortado)

Tenga en cuenta que el código está diseñado para el procesamiento a largo plazo en CLI SAPI .

Para protocolos personalizados, considere usar API de bajo nivel, es decir, eventos de búfer , buffers . Para las comunicaciones SSL / TLS, recomendaría la API de bajo nivel junto con el contexto SSL del evento. Ejemplos:

Aunque la API HTTP de Libevent es simple, no es tan flexible como los eventos de búfer. Por ejemplo, la API HTTP actualmente no es compatible con los métodos HTTP personalizados. Pero es posible implementar virtualmente cualquier protocolo usando la API de bajo nivel.

Ev Extension

También escribí una muestra de otro cliente HTTP que usa la extensión Ev con sockets en modo no bloqueante . El código es un poco más detallado que la muestra basada en el evento, porque Ev es un ciclo de evento de propósito general. No proporciona funciones específicas de red, pero su observador EvIo es capaz de escuchar un descriptor de archivo encapsulado en el recurso de socket, en particular.

Este es un cliente HTTP de muestra basado en la extensión Ev .

La extensión Ev implementa un ciclo de eventos de propósito general simple pero poderoso. No proporciona vigilantes específicos de red, pero su observador de E / S se puede usar para el procesamiento asíncrono de sockets .

El siguiente código muestra cómo se pueden programar las solicitudes HTTP para el procesamiento en paralelo.

http-client.php

<?php class MyHttpRequest { /// @var MyHttpClient private $http_client; /// @var string private $address; /// @var string HTTP resource such as /page?get=param private $resource; /// @var string HTTP method such as GET, POST etc. private $method; /// @var int private $service_port; /// @var resource Socket private $socket; /// @var double Connection timeout in seconds. private $timeout = 10.; /// @var int Chunk size in bytes for socket_recv() private $chunk_size = 20; /// @var EvTimer private $timeout_watcher; /// @var EvIo private $write_watcher; /// @var EvIo private $read_watcher; /// @var EvTimer private $conn_watcher; /// @var string buffer for incoming data private $buffer; /// @var array errors reported by sockets extension in non-blocking mode. private static $e_nonblocking = [ 11, // EAGAIN or EWOULDBLOCK 115, // EINPROGRESS ]; /** * @param MyHttpClient $client * @param string $host Hostname, e.g. google.co.uk * @param string $resource HTTP resource, e.g. /page?a=b&c=d * @param string $method HTTP method: GET, HEAD, POST, PUT etc. * @throws RuntimeException */ public function __construct(MyHttpClient $client, $host, $resource, $method) { $this->http_client = $client; $this->host = $host; $this->resource = $resource; $this->method = $method; // Get the port for the WWW service $this->service_port = getservbyname(''www'', ''tcp''); // Get the IP address for the target host $this->address = gethostbyname($this->host); // Create a TCP/IP socket $this->socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP); if (!$this->socket) { throw new RuntimeException("socket_create() failed: reason: " . socket_strerror(socket_last_error())); } // Set O_NONBLOCK flag socket_set_nonblock($this->socket); $this->conn_watcher = $this->http_client->getLoop() ->timer(0, 0., [$this, ''connect'']); } public function __destruct() { $this->close(); } private function freeWatcher(&$w) { if ($w) { $w->stop(); $w = null; } } /** * Deallocates all resources of the request */ private function close() { if ($this->socket) { socket_close($this->socket); $this->socket = null; } $this->freeWatcher($this->timeout_watcher); $this->freeWatcher($this->read_watcher); $this->freeWatcher($this->write_watcher); $this->freeWatcher($this->conn_watcher); } /** * Initializes a connection on socket * @return bool */ public function connect() { $loop = $this->http_client->getLoop(); $this->timeout_watcher = $loop->timer($this->timeout, 0., [$this, ''_onTimeout'']); $this->write_watcher = $loop->io($this->socket, Ev::WRITE, [$this, ''_onWritable'']); return socket_connect($this->socket, $this->address, $this->service_port); } /** * Callback for timeout (EvTimer) watcher */ public function _onTimeout(EvTimer $w) { $w->stop(); $this->close(); } /** * Callback which is called when the socket becomes wriable */ public function _onWritable(EvIo $w) { $this->timeout_watcher->stop(); $w->stop(); $in = implode("/r/n", [ "{$this->method} {$this->resource} HTTP/1.1", "Host: {$this->host}", ''Connection: Close'', ]) . "/r/n/r/n"; if (!socket_write($this->socket, $in, strlen($in))) { trigger_error("Failed writing $in to socket", E_USER_ERROR); return; } $loop = $this->http_client->getLoop(); $this->read_watcher = $loop->io($this->socket, Ev::READ, [$this, ''_onReadable'']); // Continue running the loop $loop->run(); } /** * Callback which is called when the socket becomes readable */ public function _onReadable(EvIo $w) { // recv() 20 bytes in non-blocking mode $ret = socket_recv($this->socket, $out, 20, MSG_DONTWAIT); if ($ret) { // Still have data to read. Append the read chunk to the buffer. $this->buffer .= $out; } elseif ($ret === 0) { // All is read printf("/n<<<</n%s/n>>>>", rtrim($this->buffer)); fflush(STDOUT); $w->stop(); $this->close(); return; } // Caught EINPROGRESS, EAGAIN, or EWOULDBLOCK if (in_array(socket_last_error(), static::$e_nonblocking)) { return; } $w->stop(); $this->close(); } } ///////////////////////////////////// class MyHttpClient { /// @var array Instances of MyHttpRequest private $requests = []; /// @var EvLoop private $loop; public function __construct() { // Each HTTP client runs its own event loop $this->loop = new EvLoop(); } public function __destruct() { $this->loop->stop(); } /** * @return EvLoop */ public function getLoop() { return $this->loop; } /** * Adds a pending request */ public function addRequest(MyHttpRequest $r) { $this->requests []= $r; } /** * Dispatches all pending requests */ public function run() { $this->loop->run(); } } ///////////////////////////////////// // Usage $client = new MyHttpClient(); foreach (range(1, 10) as $i) { $client->addRequest(new MyHttpRequest($client, ''my-host.local'', ''/test.php?a='' . $i, ''GET'')); } $client->run();

Pruebas

Supongamos que el script http://my-host.local/test.php está imprimiendo el volcado de $_GET :

<?php echo ''GET: '', var_export($_GET, true), PHP_EOL;

Entonces, el resultado del comando php http-client.php será similar al siguiente:

<<<< HTTP/1.1 200 OK Server: nginx/1.10.1 Date: Fri, 02 Dec 2016 12:39:54 GMT Content-Type: text/html; charset=UTF-8 Transfer-Encoding: chunked Connection: close X-Powered-By: PHP/7.0.13-pl0-gentoo 1d GET: array ( ''a'' => ''3'', ) 0 >>>> <<<< HTTP/1.1 200 OK Server: nginx/1.10.1 Date: Fri, 02 Dec 2016 12:39:54 GMT Content-Type: text/html; charset=UTF-8 Transfer-Encoding: chunked Connection: close X-Powered-By: PHP/7.0.13-pl0-gentoo 1d GET: array ( ''a'' => ''2'', ) 0 >>>> ...

(recortado)

Tenga en cuenta que en PHP 5, la extensión de sockets puede registrar advertencias para los EINPROGRESS , EAGAIN y EWOULDBLOCK errno . Es posible desactivar los registros con

error_reporting(E_ERROR);

En relación con "el resto" del Código

Solo quiero hacer algo como file_get_contents() , pero no esperar a que termine la solicitud antes de ejecutar el resto de mi código.

El código que se supone que se ejecuta en paralelo con las solicitudes de red se puede ejecutar dentro de una devolución de llamada de un temporizador de eventos o un observador inactivo de Ev, por ejemplo. Puede resolverlo fácilmente mirando las muestras mencionadas anteriormente. De lo contrario, agregaré otro ejemplo :)


  1. Simular un aborto de solicitud utilizando CURL configurando un CURLOPT_TIMEOUT_MS bajo

  2. establezca ignore_user_abort(true) para seguir procesando después de cerrar la conexión.

Con este método no es necesario implementar el manejo de la conexión a través de los encabezados y el búfer que también depende del sistema operativo, el navegador y la versión de PHP

Proceso maestro

function async_curl($background_process=''''){ //-------------get curl contents---------------- $ch = curl_init($background_process); curl_setopt_array($ch, array( CURLOPT_HEADER => 0, CURLOPT_RETURNTRANSFER =>true, CURLOPT_NOSIGNAL => 1, //to timeout immediately if the value is < 1000 ms CURLOPT_TIMEOUT_MS => 50, //The maximum number of mseconds to allow cURL functions to execute CURLOPT_VERBOSE => 1, CURLOPT_HEADER => 1 )); $out = curl_exec($ch); //-------------parse curl contents---------------- //$header_size = curl_getinfo($ch, CURLINFO_HEADER_SIZE); //$header = substr($out, 0, $header_size); //$body = substr($out, $header_size); curl_close($ch); return true; } async_curl(''http://example.com/background_process_1.php'');

Proceso de fondo

ignore_user_abort(true); //do something...

nótese bien

Si desea que cURL expire en menos de un segundo, puede usar CURLOPT_TIMEOUT_MS, aunque hay un error / "función" en "sistemas tipo Unix" que hace que libcurl expire el tiempo de inmediato si el valor es <1000 ms con el error " Error cURL (28): se alcanzó el tiempo de espera ". La explicación de este comportamiento es:

[...]

La solución es desactivar señales usando CURLOPT_NOSIGNAL

Recursos


Aquí está mi propia función PHP cuando hago POST a una URL específica de cualquier página ... Muestra: *** uso de mi Función ...

<?php parse_str("[email protected]&subject=this is just a test"); $_POST[''email'']=$email; $_POST[''subject'']=$subject; echo HTTP_POST("http://example.com/mail.php",$_POST);*** exit; ?> <?php /*********HTTP POST using FSOCKOPEN **************/ // by ArbZ function HTTP_Post($URL,$data, $referrer="") { // parsing the given URL $URL_Info=parse_url($URL); // Building referrer if($referrer=="") // if not given use this script as referrer $referrer=$_SERVER["SCRIPT_URI"]; // making string from $data foreach($data as $key=>$value) $values[]="$key=".urlencode($value); $data_string=implode("&",$values); // Find out which port is needed - if not given use standard (=80) if(!isset($URL_Info["port"])) $URL_Info["port"]=80; // building POST-request: HTTP_HEADERs $request.="POST ".$URL_Info["path"]." HTTP/1.1/n"; $request.="Host: ".$URL_Info["host"]."/n"; $request.="Referer: $referer/n"; $request.="Content-type: application/x-www-form-urlencoded/n"; $request.="Content-length: ".strlen($data_string)."/n"; $request.="Connection: close/n"; $request.="/n"; $request.=$data_string."/n"; $fp = fsockopen($URL_Info["host"],$URL_Info["port"]); fputs($fp, $request); while(!feof($fp)) { $result .= fgets($fp, 128); } fclose($fp); //$eco = nl2br(); function getTextBetweenTags($string, $tagname) { $pattern = "/<$tagname ?.*>(.*)<//$tagname>/"; preg_match($pattern, $string, $matches); return $matches[1]; } //STORE THE FETCHED CONTENTS to a VARIABLE, because its way better and fast... $str = $result; $txt = getTextBetweenTags($str, "span"); $eco = $txt; $result = explode("&",$result); return $result[1]; <span style=background-color:LightYellow;color:blue>".trim($_GET[''em''])."</span> </pre> "; } </pre>


Aquí hay un ejemplo de trabajo, simplemente ejecútelo y abra storage.txt después, para verificar el resultado mágico

<?php function curlGet($target){ $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $target); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); $result = curl_exec ($ch); curl_close ($ch); return $result; } // Its the next 3 lines that do the magic ignore_user_abort(true); header("Connection: close"); header("Content-Length: 0"); echo str_repeat("s", 100000); flush(); $i = $_GET[''i'']; if(!is_numeric($i)) $i = 1; if($i > 4) exit; if($i == 1) file_put_contents(''storage.txt'', ''''); file_put_contents(''storage.txt'', file_get_contents(''storage.txt'') . time() . "/n"); sleep(5); curlGet($_SERVER[''HTTP_HOST''] . $_SERVER[''SCRIPT_NAME''] . ''?i='' . ($i + 1)); curlGet($_SERVER[''HTTP_HOST''] . $_SERVER[''SCRIPT_NAME''] . ''?i='' . ($i + 1));



La extensión swoole. https://github.com/matyhtf/swoole Framework asincrónico y de redes concurrentes para PHP.

$client = new swoole_client(SWOOLE_SOCK_TCP, SWOOLE_SOCK_ASYNC); $client->on("connect", function($cli) { $cli->send("hello world/n"); }); $client->on("receive", function($cli, $data){ echo "Receive: $data/n"; }); $client->on("error", function($cli){ echo "connect fail/n"; }); $client->on("close", function($cli){ echo "close/n"; }); $client->connect(''127.0.0.1'', 9501, 0.5);


La respuesta que había aceptado previamente no funcionó. Aún esperaba respuestas. Sin embargo, esto funciona, tomado de ¿Cómo hago una solicitud GET asíncrona en PHP?

function post_without_wait($url, $params) { foreach ($params as $key => &$val) { if (is_array($val)) $val = implode('','', $val); $post_params[] = $key.''=''.urlencode($val); } $post_string = implode(''&'', $post_params); $parts=parse_url($url); $fp = fsockopen($parts[''host''], isset($parts[''port''])?$parts[''port'']:80, $errno, $errstr, 30); $out = "POST ".$parts[''path'']." HTTP/1.1/r/n"; $out.= "Host: ".$parts[''host'']."/r/n"; $out.= "Content-Type: application/x-www-form-urlencoded/r/n"; $out.= "Content-Length: ".strlen($post_string)."/r/n"; $out.= "Connection: Close/r/n/r/n"; if (isset($post_string)) $out.= $post_string; fwrite($fp, $out); fclose($fp); }


Puede hacer trucos usando exec () para invocar algo que puede hacer solicitudes HTTP, como wget , pero debe dirigir todos los resultados del programa a algún lugar, como un archivo o / dev / null, de lo contrario, el proceso de PHP esperará a que salida.

Si desea separar por completo el proceso del hilo de apache, intente algo como (no estoy seguro de esto, pero espero que entienda la idea):

exec(''bash -c "wget -O (url goes here) > /dev/null 2>&1 &"'');

No es un buen negocio, y es probable que desee algo así como un trabajo cron invocando un script de latido que sondea una cola de evento de base de datos real para hacer eventos asincrónicos reales.


Puede usar esta biblioteca: https://github.com/stil/curl-easy

Es bastante sencillo entonces:

<?php $request = new cURL/Request(''http://yahoo.com/''); $request->getOptions()->set(CURLOPT_RETURNTRANSFER, true); // Specify function to be called when your request is complete $request->addListener(''complete'', function (cURL/Event $event) { $response = $event->response; $httpCode = $response->getInfo(CURLINFO_HTTP_CODE); $html = $response->getContent(); echo "/nDone./n"; }); // Loop below will run as long as request is processed $timeStart = microtime(true); while ($request->socketPerform()) { printf("Running time: %dms /r", (microtime(true) - $timeStart)*1000); // Here you can do anything else, while your request is in progress }

A continuación puede ver la salida de la consola del ejemplo anterior. Mostrará un simple reloj en vivo que indica la cantidad de tiempo que se está ejecutando la solicitud:


Puede usar sockets que no sean de bloqueo y una de las extensiones pecl para PHP:

Puede usar la biblioteca que le proporciona una capa de abstracción entre su código y una extensión pecl: https://github.com/reactphp/event-loop

También puede usar un cliente http asincrónico, basado en la biblioteca anterior: https://github.com/reactphp/http-client

Ver otras bibliotecas de ReactPHP: http://reactphp.org

Tenga cuidado con un modelo asincrónico. Recomiendo ver este video en youtube: http://www.youtube.com/watch?v=MWNcItWuKpI


Si controla el objetivo que desea llamar de forma asincrónica (por ejemplo, su propio "longtask.php"), puede cerrar la conexión desde ese extremo, y ambos scripts se ejecutarán en paralelo. Funciona así:

  1. quick.php abre longtask.php a través de cURL (no magia aquí)
  2. longtask.php cierra la conexión y continúa (¡mágico!)
  3. cURL vuelve a quick.php cuando la conexión está cerrada
  4. Ambas tareas continúan en paralelo

Lo he intentado y funciona muy bien. Pero quick.php no sabrá nada sobre longtask.php, a menos que crees algún medio de comunicación entre los procesos.

Pruebe este código en longtask.php, antes de hacer cualquier otra cosa. Cerrará la conexión, pero aún continuará ejecutándose (y suprimirá cualquier salida):

while(ob_get_level()) ob_end_clean(); header(''Connection: close''); ignore_user_abort(); ob_start(); echo(''Connection Closed''); $size = ob_get_length(); header("Content-Length: $size"); ob_end_flush(); flush();

El código se copia de las notas aportadas por el usuario del manual de PHP y se mejora algo.


déjame mostrarte mi camino :)

necesita nodejs instalado en el servidor

(mi servidor envía 1000 https obtener solicitud tarda solo 2 segundos)

url.php:

<? $urls = array_fill(0, 100, ''http://google.com/blank.html''); function execinbackground($cmd) { if (substr(php_uname(), 0, 7) == "Windows"){ pclose(popen("start /B ". $cmd, "r")); } else { exec($cmd . " > /dev/null &"); } } fwite(fopen("urls.txt","w"),implode("/n",$urls); execinbackground("nodejs urlscript.js urls.txt"); // { do your work while get requests being executed.. } ?>

urlscript.js>

var https = require(''https''); var url = require(''url''); var http = require(''http''); var fs = require(''fs''); var dosya = process.argv[2]; var logdosya = ''log.txt''; var count=0; http.globalAgent.maxSockets = 300; https.globalAgent.maxSockets = 300; setTimeout(timeout,100000); // maximum execution time (in ms) function trim(string) { return string.replace(/^/s*|/s*$/g, '''') } fs.readFile(process.argv[2], ''utf8'', function (err, data) { if (err) { throw err; } parcala(data); }); function parcala(data) { var data = data.split("/n"); count=''''+data.length+''-''+data[1]; data.forEach(function (d) { req(trim(d)); }); /* fs.unlink(dosya, function d() { console.log(''<%s> file deleted'', dosya); }); */ } function req(link) { var linkinfo = url.parse(link); if (linkinfo.protocol == ''https:'') { var options = { host: linkinfo.host, port: 443, path: linkinfo.path, method: ''GET'' }; https.get(options, function(res) {res.on(''data'', function(d) {});}).on(''error'', function(e) {console.error(e);}); } else { var options = { host: linkinfo.host, port: 80, path: linkinfo.path, method: ''GET'' }; http.get(options, function(res) {res.on(''data'', function(d) {});}).on(''error'', function(e) {console.error(e);}); } } process.on(''exit'', onExit); function onExit() { log(); } function timeout() { console.log("i am too far gone");process.exit(); } function log() { var fd = fs.openSync(logdosya, ''a+''); fs.writeSync(fd, dosya + ''-''+count+''/n''); fs.closeSync(fd); }


esto necesita php5, lo robé de docs.php.net y edité el final.

Lo uso para monitorear cuando ocurre un error en el sitio de un cliente, me envía datos sin detener la salida

function do_post_request($url, $data, $optional_headers = null,$getresponse = false) { $params = array( ''http'' => array( ''method'' => ''POST'', ''content'' => $data ) ); if ($optional_headers !== null) { $params[''http''][''header''] = $optional_headers; } $ctx = stream_context_create($params); $fp = @fopen($url, ''rb'', false, $ctx); if (!$fp) { return false; } if ($getresponse) { $response = stream_get_contents($fp); return $response; } return true; }


/** * Asynchronously execute/include a PHP file. Does not record the output of the file anywhere. * * @param string $filename file to execute, relative to calling script * @param string $options (optional) arguments to pass to file via the command line */ function asyncInclude($filename, $options = '''') { exec("/path/to/php -f {$filename} {$options} >> /dev/null &"); }


class async_file_get_contents extends Thread{ public $ret; public $url; public $finished; public function __construct($url) { $this->finished=false; $this->url=$url; } public function run() { $this->ret=file_get_contents($this->url); $this->finished=true; } } $afgc=new async_file_get_contents("http://example.org/file.ext");