Comment faire des requêtes HTTP asynchrones en PHP

y a-t-il un moyen en PHP de faire des appels HTTP asynchrones? Je ne me soucie pas de la réponse, je veux juste faire quelque chose comme file_get_contents() , mais pas attendre que la requête se termine avant d'exécuter le reste de mon code. Ce serait super utile pour déclencher des "événements" d'une sorte dans mon application, ou déclencher des processus longs.

des idées?

172
demandé sur Simon East 2008-09-24 03:00:53

16 réponses

la réponse que j'avais précédemment acceptée n'a pas fonctionné. Elle attendait toujours des réponses. Cela fonctionne cependant, pris dans Comment faire une requête asynchrone GET 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);
}
41
répondu UltimateBrent 2017-05-23 11:54:36

cela nécessite php5, Je l'ai volé. docs.php.net et édité la fin.

Je l'utilise pour surveiller quand une erreur se produit sur un site client, il envoie des données hors de moi sans retarder la sortie

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;
}
25
répondu Bruce Aldridge 2017-04-18 14:30:22

si vous contrôlez la cible que vous voulez appeler asynchrone (par exemple votre propre" longtask.php"), vous pouvez fermer la connexion à partir de cette fin, et les deux scripts s'exécutent en parallèle. Cela fonctionne comme ceci:

  1. rapide.php s'ouvre longtask.php via cURL (pas de magie ici)
  2. longtask.php ferme la connexion et continue (magic!)
  3. retourne à quick.php lorsque la connexion est fermée
  4. Les deux tâches se poursuivent en parallèle

j'ai essayé, et ça marche très bien. Mais rapide.php ne saura rien sur la durée de la tâche.php le fait, sauf si vous créez un moyen de communication entre les processus.

essayez ce code à longtask.php, avant de faire quoi que ce soit d'autre. Il fermera la connexion, mais continuera d'exécuter (et supprimera toute sortie):

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

le code est copié du PHP manuel de l'utilisateur contribué notes et quelque peu améliorée.

24
répondu Christian Davén 2010-02-13 18:22:58

vous pouvez faire de la supercherie en utilisant exec() pour invoquer quelque chose qui peut faire des requêtes HTTP, comme wget , mais vous devez diriger toutes les sorties du programme vers quelque part, comme un fichier ou /dev/null, sinon le processus PHP attendra cette sortie.

si vous voulez séparer entièrement le processus du fil apache, essayez quelque chose comme (je ne suis pas sûr de cela, mais j'espère que vous avez l'idée):

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

ce n'est pas une bonne affaire, et vous voudrez probablement quelque chose comme un travail de cron invoquant un script heartbeat qui scrute une file d'événements réelle de la base de données pour faire de vrais événements asynchrones.

14
répondu Internet Friend 2008-09-23 23:35:26
/**
 * 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 &");
}
8
répondu philfreo 2010-03-13 07:18:03
  1. Faux une demande d'avortement en utilisant CURL mise à bas CURLOPT_TIMEOUT_MS

  2. set ignore_user_abort(true) pour garder le traitement après la fermeture de la connexion.

avec cette méthode pas besoin de mettre en œuvre la gestion de la connexion via les en-têtes et le tampon trop dépendant de L'OS, du navigateur et de la version PHP

processus Maître

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

processus d'arrière-plan

ignore_user_abort(true);

//do something...

NB

si vous voulez cURL à temps d'arrêt dans moins d'une seconde, vous pouvez utiliser CURLOPT_TIMEOUT_MS, bien qu'il y ait un bug/"feature" sur "Unix-like les systèmes " qui provoquent l'arrêt immédiat de libcurl si la valeur est < 1000 ms avec l'erreur "cURL Error (28): Timeout was reached". Le explication pour ce comportement est:

[...]

la solution consiste à désactiver les signaux en utilisant CURLOPT_NOSIGNAL

ressources

6
répondu RafaSashi 2017-05-23 12:26:00

permettez-moi de vous montrer ma façon :)

nécessite l'installation de nodejs sur le serveur

(mon serveur envoie 1000 https demande ne prend que 2 secondes)

de l'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);
}
4
répondu user1031143 2012-02-08 19:20:42

vous pouvez utiliser cette bibliothèque: https://github.com/stil/curl-easy

c'est assez simple alors:

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

ci-dessous vous pouvez voir la sortie de la console de l'exemple ci-dessus. Il affichera simple live clock indiquant combien de temps demande est en cours d'exécution:


animation

4
répondu stil 2015-05-19 00:27:32

vous pouvez utiliser des sockets non-bloquants et une des extensions pecl pour PHP:

Vous pouvez utiliser la bibliothèque qui vous donne une abstraction couche entre votre code et une extension pecl: https://github.com/reactphp/event-loop

vous pouvez également utiliser async http-client, basé sur la bibliothèque précédente: https://github.com/reactphp/http-client

Voir autres bibliothèques de ReactPHP: http://reactphp.org

soyez prudent avec un modèle asynchrone. Je recommande de voir cette vidéo sur youtube: http://www.youtube.com/watch?v=MWNcItWuKpI

3
répondu Roman Shamritskiy 2014-06-18 15:20:42
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");
3
répondu hanshenrik 2015-02-27 12:35:17

La swoole extension. https://github.com/matyhtf/swoole Asynchrone et simultanées de réseautage framework pour 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);
2
répondu Tony 2014-03-03 06:06:10
"1519170920 De L'Événement" Extension

Événement extension est très approprié. C'est un port de Libevent bibliothèque qui est conçu pour l'event-driven I/O, principalement pour la mise en réseau.

j'ai écrit un exemple de client HTTP qui permet de programmer un certain nombre de Les requêtes HTTP et les exécuter de manière asynchrone.

il s'agit d'un exemple de classe client HTTP basé sur L'événement extension.

la classe permet de programmer un certain nombre de requêtes HTTP, puis de les exécuter de manière asynchrone.

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

Ceci est un exemple de script côté serveur.

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

Utilisation

php http-client.php

Sortie De L'Échantillon

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

(Paré.)

Note, le code est conçu pour le traitement à long terme dans le CLI SAPI .


pour les protocoles personnalisés, envisagez D'utiliser L'API de bas niveau, c.-à-d. événements tampons , tampons . Pour les communications SSL/TLS, je recommande L'API de bas niveau en conjonction avec L'événement SSL context . Exemples:


bien que L'API HTTP de Libevent soit simple, elle n'est pas aussi flexible que les événements buffer. Par exemple, L'API HTTP ne supporte pas les méthodes HTTP personnalisées. Mais il est possible d'implémenter pratiquement n'importe quel protocole en utilisant L'API de bas niveau.

Ev Extension

j'ai aussi écrit un échantillon d'un autre client HTTP utilisant EV extension avec sockets dans non-blocking mode . Le code est légèrement plus verbeux que l'échantillon basé sur L'événement, car Ev est une boucle d'événement à usage général. Il ne fournit pas de fonctions spécifiques au réseau, mais son watcher EvIo est capable d'écouter un descripteur de fichier encapsulé dans la socket des ressources, en particulier.

il s'agit d'un exemple de client HTTP basé sur EV extension.

EV extension implémente une boucle d'événement simple mais puissante. Il ne fournit pas de watchers spécifiques au réseau, mais son I/O watcher peut être utilisé pour le traitement asynchrone de sockets .

le code suivant montre comment les requêtes HTTP peuvent être prévu pour un traitement parallèle.

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

test

Suppose http://my-host.local/test.php script imprime le dump de $_GET :

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

puis la sortie de la commande php http-client.php sera similaire à la suivante:

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

(paré)

Note, en PHP 5 Le les sockets extension peuvent enregistrer les avertissements pour les valeurs EINPROGRESS , EAGAIN , et EWOULDBLOCK errno . Il est possible de désactiver les logs avec

error_reporting(E_ERROR);

concernant "le reste" du Code

je veux juste faire quelque chose comme file_get_contents() , mais pas attendre que la requête se termine avant d'exécuter le reste de mon code.

Le code qui est censé fonctionner en parallèle avec le réseau, les requêtes peuvent être exécutées à l'intérieur d'un rappel d'un Événement timer , ou Ev inactif watcher , par exemple. Vous pouvez facilement le comprendre en regardant les exemples mentionnés ci-dessus. Sinon, j'ajouterai un autre exemple :)

2
répondu Ruslan Osmanov 2017-09-22 14:37:13

depuis 2018, Guzzle est devenu la bibliothèque standard de defacto pour les requêtes HTTP, utilisé dans plusieurs cadres modernes. Il est écrit en PHP pur et ne nécessite pas l'installation d'extensions personnalisées.

il peut faire des appels HTTP asynchrones très bien, et même les regrouper comme quand vous avez besoin de faire 100 appels HTTP, mais ne veulent pas exécuter plus de 5 à la fois.

exemple de requête concurrente

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]

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

2
répondu Simon East 2018-07-09 06:02:24

voici un exemple de travail, il suffit de l'exécuter et d'ouvrir le stockage.txt ensuite, pour vérifier le résultat magique

<?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));
1
répondu AlexTR 2014-06-09 23:56:38

voici ma propre fonction PHP quand je poste à une URL spécifique de n'importe quelle page.... De l'échantillon: *** l'utilisation de ma Fonction...

    <?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>
1
répondu i am ArbZ 2017-04-18 15:47:56

Eh bien, le délai peut être réglé en millisecondes, voir "CURLOPT_CONNECTTIMEOUT_MS" dans http://www.php.net/manual/en/function.curl-setopt

-4
répondu Akhil Sikri 2017-09-23 00:04:36