Frage

Gibt es eine Möglichkeit in PHP asynchrone HTTP-Anrufe zu tätigen? Ich kümmere mich nicht um die Antwort, ich will nur so etwas wie file_get_contents() tun, aber nicht warten, bis die Anforderung vor der Ausführung für den Rest meines Codes zu beenden. Dies wäre super nützlich sein für die Einstellung off „Ereignisse“ von einer Art in meiner Anwendung oder Triggern lange Prozesse.

Irgendwelche Ideen?

War es hilfreich?

Lösung

Die Antwort, die ich bisher angenommen habe nicht funktioniert. Es wartete noch auf Antworten. Dies funktioniert allerdings genommen von Wie kann ich eine machen asynchron-GET-Anforderung in 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);
}

Andere Tipps

Wenn Sie das Ziel steuern, die Sie asynchron aufgerufen werden sollen (zum Beispiel Ihres eigenen „longtask.php“), können Sie die Verbindung von diesem Ende schließen, und beide Skripte parallel ausgeführt werden. Es funktioniert wie folgt:

  1. quick.php öffnet longtask.php über cURL (hier keine Magie)
  2. longtask.php schließt die Verbindung und setzt (Magie!)
  3. cURL kehrt zu quick.php wenn die Verbindung geschlossen ist
  4. weiter Beide Aufgaben parallel

Das habe ich versucht, und es funktioniert gut. Aber quick.php wird nichts darüber wissen, wie longtask.php tut, es sei denn, Sie einige Mittel der Kommunikation zwischen den Prozessen erstellen.

Versuchen Sie diesen Code in longtask.php, bevor Sie etwas anderes tun. Es wird die Verbindung schließen, aber immer noch läuft weiter (und unterdrückt jede Ausgabe):

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();

Der Code wird von dem PHP Handbuch der kopierten Benutzer Notizen beigetragen und etwas verbessert.

Dazu braucht php5, Ich habe es aus docs.php.net und bearbeiten das Ende.

ich es für die Überwachung verwenden, wenn ein Fehler auf einer Website Kunden geschieht, sendet er Daten von mir, ohne den Ausgang hält

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

Sie können Tricks tun, indem Sie exec () etwas aufzurufen, die HTTP-Anforderungen zu tun, wie wget, aber Sie müssen alle Ausgaben aus dem Programm irgendwo lenken, wie eine Datei oder / dev / null, andernfalls wird der PHP-Prozess wird warten auf diesen Ausgang.

Wenn Sie völlig den Prozess von dem Apache-Thread zu trennen, versuchen Sie so etwas wie (ich bin darüber nicht sicher, aber ich hoffe, Sie bekommen die Idee):

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

Es ist kein schönes Geschäft, und Sie werden wahrscheinlich so etwas wie ein Cron-Job wollen einen Herzschlag-Skript aufgerufen wird, die Umfragen eine aktuelle Datenbank Ereigniswarteschlange echte asynchrone Ereignisse zu tun.

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

Ab 2018 Guzzle die Defacto-Standard-Bibliothek für HTTP-Anfragen worden ist , in mehrere modernen Frameworks verwendet. Es ist in reinem PHP geschrieben und benötigt keine benutzerdefinierten Erweiterungen installieren.

Es kann tun asynchrone HTTP-Anrufe sehr schön und sogar bündeln sie wie wenn Sie benötigen 100 HTTP-Anrufe zu tätigen, wollen aber nicht mehr als 5 zu einem Zeitpunkt ausgeführt werden.

Concurrent Anfrage Beispiel

use GuzzleHttp\Client;
use GuzzleHttp\Promise;

$client = new Client(['base_uri' => 'http://httpbin.org/']);

// Initiate each request but do not block
$promises = [
    'image' => $client->getAsync('/image'),
    'png'   => $client->getAsync('/image/png'),
    'jpeg'  => $client->getAsync('/image/jpeg'),
    'webp'  => $client->getAsync('/image/webp')
];

// Wait on all of the requests to complete. Throws a ConnectException
// if any of the requests fail
$results = Promise\unwrap($promises);

// Wait for the requests to complete, even if some of them fail
$results = Promise\settle($promises)->wait();

// You can access each result using the key provided to the unwrap
// function.
echo $results['image']['value']->getHeader('Content-Length')[0]
echo $results['png']['value']->getHeader('Content-Length')[0]

Siehe http://docs.guzzlephp.org/en/stable /quickstart.html#concurrent-requests

  1. Gefälschte eine Anforderung Abtreibung mit CURL eine niedrige CURLOPT_TIMEOUT_MS Einstellung

  2. set ignore_user_abort(true) zu halte Verarbeitung, nachdem die Verbindung geschlossen.

Mit dieser Methode keine Notwendigkeit Verbindung zu implementieren über Header Handling und Puffer zu abhängig von Betriebssystem, Browser und PHP-Version

Master-Prozess

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');

Hintergrund Prozess

ignore_user_abort(true);

//do something...

NB

  

Wenn Sie cURL in weniger als einer Sekunde Timeout möchten, können Sie verwenden   CURLOPT_TIMEOUT_MS, obwohl es ein Bug / "Feature" auf „Unix-artigen   Systeme“, die Libcurl führt sofort Timeout, wenn der Wert <   1000 ms mit dem Fehler "cURL Fehler (28): Timeout erreicht wurde". Das   Erklärung für dieses Verhalten ist:

     

[...]

     

Die Lösung ist, um Signale zu deaktivieren mit CURLOPT_NOSIGNAL

Ressourcen

Sie können diese Bibliothek verwenden: https://github.com/stil/curl-easy

Es ist ziemlich einfach, dann:

<?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
}

Im Folgenden finden Sie die Konsolenausgabe des obigen Beispiels sehen können. Es wird einfach Live-Uhr anzeigt, die angibt, wie viel Zeit Anfrage ausgeführt wird:


Animation

Lassen Sie mich Ihnen zeigen, meine Art und Weise:)

muss NodeJS auf dem Server installiert

(mein Server sendet 1000 https get Anfrage dauert nur 2 Sekunden)

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

Sie können mit Steckdosen und einem von PECL-Erweiterungen für PHP non-blocking:

Sie können die Bibliothek benutzen, die Ihnen eine Abstraktionsschicht zwischen Ihrem Code und PECL-Erweiterung gibt: https: // github.com/reactphp/event-loop

Sie können auch Asynchron-http-Client verwenden, auf der Grundlage der früheren Bibliothek: https://github.com / reactphp / http-client

Sehen Sie andere Bibliotheken von ReactPHP: http://reactphp.org

Seien Sie vorsichtig mit einem asynchronen Modell. Ich empfehle dieses Video auf youtube zu sehen: http://www.youtube.com/watch?v= MWNcItWuKpI

Die swoole Erweiterung. https://github.com/matyhtf/swoole Asynchrone & gleichzeitige Vernetzung Framework für 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);
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");

Event-Erweiterung

Ereignis Erweiterung ist sehr gut geeignet. Es ist eine Portierung von Libevent -Bibliothek, die für ereignisgesteuerte I / O, vor allem für die Vernetzung ausgelegt ist.

Ich habe eine Probe HTTP-Client geschrieben, die eine Nummer planen ermöglicht von HTTP-Anforderungen und führen sie asynchron.

Dies ist ein Beispiel für eine HTTP-Client-Klasse basiert auf Ereignis Erweiterung.

Die Klasse ermöglicht eine Reihe von HTTP-Anforderungen zu planen, dann sie asynchron ausgeführt werden.

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

Dies ist ein Beispielskript auf der Serverseite.

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

Verwendung

php http-client.php

Beispielausgabe

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',
)
...

(getrimmt).

Beachten Sie, wird der Code für die Langzeitverarbeitung in der CLI SAPI .


Für kundenspezifische Protokolle, sollten Low-Level-API, das heißt Puffer Ereignisse , Puffer . Für SSL / TLS-Kommunikation, würde ich den Low-Level-API in Verbindung mit Ereignisse empfehlen ssl Kontext . Beispiele:


Obwohl Libevent HTTP-API einfach ist, ist es nicht so flexibel wie Puffer Ereignisse. Zum Beispiel ist der HTTP-API zur Zeit keine benutzerdefinierten HTTP-Methoden unterstützen. Aber es ist möglich, praktisch jedes Protokoll zu implementieren unter Verwendung des Low-Level-API.

Ev Erweiterung

Ich habe auch eine Probe eines anderen HTTP-Client geschrieben mit Ev Erweiterung mit Steckdosen in nicht-blockierenden Modus . Der Code ist etwas ausführlicher als die Probe basierend auf Ereignis, weil Ev eine Allzweck-Ereignisschleife ist. Dabei spielt es keine netzwerkspezifische Funktionen zur Verfügung stellen, aber seine EvIo Beobachter sind in der Lage in die Buchse Ressource eingekapselten zu einem Dateideskriptor hören, insbesondere.

Dies ist ein Beispiel HTTP-Client basiert auf Ev Erweiterung.

Ev Erweiterung implementiert eine einfache, aber leistungsfähige Ereignisschleife für allgemeine Zwecke. Es bietet keine netzspezifische Beobachter, aber seine I / O-Beobachter kann für asynchrone Verarbeitung von Steckdosen verwendet werden.

Der folgende Code zeigt, wie HTTP-Anforderungen können für die parallele Verarbeitung geplant werden.

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();

Testing

Angenommen http://my-host.local/test.php Skript druckt den Dump von $_GET:

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

Dann ist der Ausgang von php http-client.php Befehl wird wie folgt aus:

<<<<
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
>>>>
...

(getrimmt)

Hinweis, in PHP 5 die Steckdosen Erweiterung Warnungen für EINPROGRESS, EAGAIN und EWOULDBLOCK errno Werte einloggen können. Es ist möglich, die Protokolle mit

auszuschalten
error_reporting(E_ERROR);

In Bezug auf "Der Rest" des Kodex

  

Ich will nur so etwas wie file_get_contents() tun, aber nicht warten, bis die Anforderung vor der Ausführung für den Rest meines Code zu beenden.

Der Code, soll parallel zu den Netzwerkanforderungen laufen innerhalb eines den Rückruf eines Event-Timer oder Ev Idle Beobachter , zum Beispiel. Sie können es leicht herausfinden, indem die Proben oben genannten beobachten. Ansonsten werde ich ein weiteres Beispiel hinzu:)

Hier ist ein funktionierendes Beispiel, nur um es läuft und offene storage.txt danach, das magische Ergebnis zu überprüfen

<?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));

Hier ist meine eigene PHP-Funktion, wenn ich POST zu einer bestimmten URL jeder Seite .... Beispiel: *** Verwendung meiner Funktion ...

    <?php
        parse_str("email=myemail@ehehehahaha.com&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>

ReactPHP Asynchron-http-Client
https://github.com/shuchkin/react-http-client

über Composer installieren

$ composer require shuchkin/react-http-client

Async HTTP GET

// get.php
$loop = \React\EventLoop\Factory::create();

$http = new \Shuchkin\ReactHTTP\Client( $loop );

$http->get( 'https://tools.ietf.org/rfc/rfc2068.txt' )->then(
    function( $content ) {
        echo $content;
    },
    function ( \Exception $ex ) {
        echo 'HTTP error '.$ex->getCode().' '.$ex->getMessage();
    }
);

$loop->run();

Ausführen php in CLI-Modus

$ php get.php

Nun, das Timeout kann in Millisekunden eingestellt werden, siehe "CURLOPT_CONNECTTIMEOUT_MS" in http://www.php.net/manual/en /function.curl-setopt

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top