Wie mache ich eine asynchrone GET-Anfrage in PHP?

97

Ich möchte eine einfache GET-Anfrage an ein anderes Skript auf einem anderen Server senden. Wie mache ich das?

In einem Fall muss ich nur ein externes Skript anfordern, ohne dass eine Ausgabe erforderlich ist.

make_request('http://www.externalsite.com/script1.php?variable=45'); //example usage

Im zweiten Fall muss ich die Textausgabe erhalten.

$output = make_request('http://www.externalsite.com/script2.php?variable=45');
echo $output; //string output

Um ehrlich zu sein, möchte ich nicht mit CURL herumspielen, da dies nicht wirklich die Aufgabe von CURL ist. Ich möchte auch nicht http_get verwenden, da ich nicht über die PECL-Erweiterungen verfüge.

Würde fsockopen funktionieren? Wenn ja, wie mache ich das, ohne den Inhalt der Datei einzulesen? Gibt es keinen anderen Weg?

Vielen Dank an alle

Aktualisieren

Ich sollte hinzufügen, im ersten Fall möchte ich nicht warten, bis das Skript etwas zurückgibt. Wie ich verstehe, wartet file_get_contents () darauf, dass die Seite vollständig geladen wird usw.?

Abs
quelle
6
@ William: Ja, die meisten Fragen können als exakte Duplikate von sich selbst betrachtet werden. 8-) Ich denke, Sie haben den falschen Link gepostet ...
RichieHindle
Duplikat: stackoverflow.com/questions/959063/…
Sasha Chedygov
1
Ich wollte den Link musicfreak posten, meine Tabs durcheinander bringen ;-)
William Brendel
2
@Richie: Die meisten Fragen? ;)
Sasha Chedygov
1
Ich habe die Frage umbenannt, um sie von der anderen zu unterscheiden, da Sie anscheinend eine Anfrage stellen möchten, ohne sich um die Verwendung der Antwort zu kümmern (dies kann also passieren, wenn der Rest des Skripts ausgeführt wird). Mach es rückgängig, wenn ich mich irre!
dbr

Antworten:

52

file_get_contents wird tun was du willst

$output = file_get_contents('http://www.example.com/');
echo $output;

Bearbeiten: Eine Möglichkeit, eine GET-Anforderung auszulösen und sofort zurückzukehren.

Zitiert von http://petewarden.typepad.com/searchbrowser/2008/06/how-to-post-an.html

function curl_post_async($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);
}

Öffnen Sie dazu einen Socket, lösen Sie eine Get-Anfrage aus, schließen Sie den Socket sofort und kehren Sie zurück.

Marquis Wang
quelle
6
curl_post_async sendet eine POST-Anfrage, keine GET.
Vinko Vrsalovic
13
Habe ich Recht, wenn ich sage, dass diese Funktion falsch benannt ist? Es hat wirklich nichts mit der Curl-Bibliothek zu tun. Es ist fsock_post_async () eher so
MikeMurko
61
Dies ist NICHT asynchron! Insbesondere wenn der Server auf der anderen Seite ausgefallen ist, bleibt dieser Code 30 Sekunden lang hängen (der 5. Parameter im fsockopen). Außerdem wird die Ausführung des fwrite seine süße Zeit in Anspruch nehmen (die Sie mit stream_set_timeout ($ fp, $ my_timeout) begrenzen können. Das Beste, was Sie tun können, ist, ein niedriges Timeout für fsockopen auf 0,1 (100 ms) und $ my_timeout auf 100 ms festzulegen Sie riskieren jedoch, dass die Anfrage Timeout.
Chris Cinelli
4
Dies hat nichts mit Async zu tun. Dies ist so synchron wie es nur geht ... Asynchron bedeutet, andere Aufgaben zu erledigen, während diese Aufgabe ausgeführt wird. Es ist eine parallele Ausführung.
CodeAngry
17
Dies ist weder asynchron noch verwendet es Curl, wie Sie es wagen, es zu nennen curl_post_asyncund sogar positive Stimmen zu erhalten ...
Daniel W.
33

So funktioniert die Antwort von Marquis sowohl mit POST- als auch mit GET-Anforderungen:

  // $type must equal 'GET' or 'POST'
  function curl_request_async($url, $params, $type='POST')
  {
      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);

      // Data goes in the path for a GET request
      if('GET' == $type) $parts['path'] .= '?'.$post_string;

      $out = "$type ".$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";
      // Data goes in the request body for a POST request
      if ('POST' == $type && isset($post_string)) $out.= $post_string;

      fwrite($fp, $out);
      fclose($fp);
  }
Catgofire
quelle
2
Dies ist ein praktisches Code-Snippet, das ich hier und da verwendet habe, aber jetzt muss ich dasselbe tun, jedoch mit einer SSL-Site. Muss ich außer dem HTTP / 1.1-Typ und dem Port noch etwas ändern?
Kevin Jhangiani
2
Als Antwort auf die Frage, ob dies für SSL verwendet werden soll, können Sie es zu SSL machen, indem Sie den Port in 443 ändern und ssl: // an den Portnamen in fsockopen anhängen: $ fp = fsockopen ("ssl: //". $ Parts ['host '],
Michael Dogger
1
"Muss ich außer dem HTTP / 1.1-Typ und dem Port noch etwas ändern?" - Ja, Sie sollten fsockopen () mit dem Hostnamen als ssl://hostnamestatt nur aufrufen hostname.
Cowlby
22
Dies ist NICHT asynchron! Insbesondere wenn der Server auf der anderen Seite ausgefallen ist, bleibt dieser Code 30 Sekunden lang hängen (der 5. Parameter im fsockopen). Außerdem wird die Ausführung des fwrite seine süße Zeit in Anspruch nehmen (die Sie mit stream_set_timeout ($ fp, $ my_timeout) begrenzen können. Das Beste, was Sie tun können, ist, ein niedriges Timeout für fsockopen auf 0,1 (100 ms) und $ my_timeout auf 100 ms festzulegen Sie riskieren jedoch, dass die Anfrage Timeout.
Chris Cinelli
1
Die Inhaltslänge sollte nicht für GET festgelegt werden. Vielleicht verursacht in einigen Szenarien kein Fehler, aber in meinem Fall wurde die Anfrage nicht von dem aufgerufenen PHP-Skript verarbeitet.
user3285954
13

In Bezug auf Ihr Update möchten Sie nicht warten, bis die gesamte Seite geladen ist. Ich denke, HEADSie suchen nach einer HTTP- Anfrage.

get_headers sollte dies tun - ich denke, es fordert nur die Header an, daher wird nicht der gesamte Seiteninhalt gesendet.

"PHP / Curl: HEAD Request dauert auf einigen Websites sehr lange" beschreibt, wie man aHEAD Anforderung mit PHP / Curl ausgeführt wird

Wenn Sie die Anforderung auslösen und das Skript überhaupt nicht aufhalten möchten, gibt es verschiedene Möglichkeiten unterschiedlicher Komplexität.

  • Führen Sie die HTTP-Anfrage als Hintergrundprozess aus, PHP führt einen Hintergrundprozess aus - im Grunde würden Sie so etwas ausführen "wget -O /dev/null $carefully_escaped_url"- dies ist plattformspezifisch und Sie müssen wirklich vorsichtig sein, wenn Sie Parameter in den Befehl einbinden
  • Ausführen eines PHP-Skripts im Hintergrund - im Grunde dasselbe wie die UNIX-Prozessmethode, jedoch Ausführen eines PHP-Skripts anstelle eines Shell-Befehls
  • Haben Sie eine "Jobwarteschlange", die eine Datenbank verwendet (oder etwas wie Beanstalkd, das wahrscheinlich übertrieben ist). Sie fügen der Warteschlange eine URL hinzu, und ein Hintergrundprozess oder ein Cron-Job sucht routinemäßig nach neuen Jobs und führt Anforderungen an die URL aus
dbr
quelle
+1 für verschiedene interessante Optionen, an die ich vorher noch nicht gedacht habe
Jasdeep Khalsa
"Ich denke, es werden nur die Header angefordert" - Vielleicht, aber nichts hindert ein Dokument daran, einen vollständigen Antworttext als Antwort auf eine HEAD-Anforderung zu senden. Und ich gehe davon aus, dass diese Methode fsock unter der Haube verwenden und es zwingen würde, auf die vollständige Antwort zu warten (und sie zu lesen).
Hiburn8
6

Das tust du nicht. PHP bietet zwar viele Möglichkeiten zum Aufrufen einer URL, bietet jedoch keine sofort einsatzbereite Unterstützung für asynchrone / Thread-Verarbeitung pro Anforderungs- / Ausführungszyklus. Jede Methode zum Senden einer Anforderung für eine URL (oder eine SQL-Anweisung oder eine usw.) wartet auf eine Antwort. Sie benötigen eine Art sekundäres System, das auf dem lokalen Computer ausgeführt wird, um dies zu erreichen (googeln Sie nach "PHP Job Queue").

Alan Storm
quelle
1
Hier gibt es einen Hack: stackoverflow.com/questions/124462/asynchronous-php-calls (Antwort von Christian Davén), aber ich stimme zu, dass eine Warteschlange der richtige Weg wäre, dies zu tun.
Chris Cinelli
Ich denke, diese Antwort von 2009 ist jetzt veraltet. Die Guzzle PHP-Bibliothek unterstützt jetzt gleichzeitige und asynchrone Anforderungen.
Simon East
6

Ich würde Ihnen eine gut getestete PHP-Bibliothek empfehlen: Curl-Easy

<?php
$request = new cURL\Request('http://www.externalsite.com/script2.php?variable=45');
$request->getOptions()
    ->set(CURLOPT_TIMEOUT, 5)
    ->set(CURLOPT_RETURNTRANSFER, true);

// add callback when the request will be completed
$request->addListener('complete', function (cURL\Event $event) {
    $response = $event->response;
    $content = $response->getContent();
    echo $content;
});

while ($request->socketPerform()) {
    // do anything else when the request is processed
}
Stil
quelle
Die Guzzle PHP-Bibliothek unterstützt auch gleichzeitige und asynchrone Anforderungen.
Simon East
Guzzle behauptet, dass es Unterstützung hat, aber das Testen seiner postAsync-Methode sieht so aus, als würde es 150 ms synchron und dann 2 ms asynchron ausführen. Ich habe mehr als eine Stunde damit verbracht, es ohne Erfolg zu beheben - würde es nicht empfehlen.
Velizar Hristov
4

Wenn Sie eine Linux-Umgebung verwenden, können Sie den Befehl exec des PHP verwenden, um die Linux-Curl aufzurufen. Hier ist ein Beispielcode, der einen asynchronen HTTP-Beitrag erstellt.

function _async_http_post($url, $json_string) {
  $run = "curl -X POST -H 'Content-Type: application/json'";
  $run.= " -d '" .$json_string. "' " . "'" . $url . "'";
  $run.= " > /dev/null 2>&1 &";
  exec($run, $output, $exit);
  return $exit == 0;
}

Dieser Code benötigt keine zusätzlichen PHP-Bibliotheken und kann den http-Beitrag in weniger als 10 Millisekunden abschließen.

Fremder
quelle
1
Dies ist eine sehr schlechte Idee: Exec scheitert oft: Stellen Sie sich vor, 6/200 Kunden erhalten keine E-Mail-Bestätigung für eine bezahlte Buchung ...
HellBaby
Dies funktionierte für mich, da ich nur einen Ping benötige, um ein anderes Skript auf einem anderen Server zu starten. Ich habe es einfach so benutzt: _async_http_post ($ url, ''); Und das funktioniert auf OVH-Servern auf Gegenseitigkeit ... Was großartig ist.
Kilowog
4
function make_request($url, $waitResult=true){
    $cmi = curl_multi_init();

    $curl = curl_init();
    curl_setopt($curl, CURLOPT_URL, $url);
    curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);

    curl_multi_add_handle($cmi, $curl);

    $running = null;
    do {
        curl_multi_exec($cmi, $running);
        sleep(.1);
        if(!$waitResult)
        break;
    } while ($running > 0);
    curl_multi_remove_handle($cmi, $curl);
    if($waitResult){
        $curlInfos = curl_getinfo($curl);
        if((int) $curlInfos['http_code'] == 200){
            curl_multi_close($cmi);
            return curl_multi_getcontent($curl);
        }
    }
    curl_multi_close($cmi);
}
amez
quelle
Sie können dafür sorgen, dass ein Objekt zurückgegeben wird, mit dem Sie getstatus()oder waitSend()oder aufrufen können waitResult(). Auf diese Weise kann der Aufrufer ein vollständig asynchrones Verhalten erhalten, indem er in einer Schleife aufruft, um zu überprüfen, ob Ergebnisse vorliegen, und wenn nicht, mit der anderen ausgeführten Aufgabe fortzufahren. Hmm, jetzt möchte ich Taskvon .net nach PHP
portieren
3

Interessantes Problem. Ich vermute, Sie möchten nur einen Prozess oder eine Aktion auf dem anderen Server auslösen, aber es ist Ihnen egal, was die Ergebnisse sind, und Sie möchten, dass Ihr Skript fortgesetzt wird. Es gibt wahrscheinlich etwas in cURL, das dies bewirken kann, aber Sie sollten in Betracht ziehen exec(), ein anderes Skript auf dem Server auszuführen, das den Aufruf ausführt, wenn cURL dies nicht kann. (Normalerweise möchten die Benutzer die Ergebnisse des Skriptaufrufs, daher bin ich mir nicht sicher, ob PHP den Prozess nur auslösen kann.) Mit können exec()Sie ein wgetoder sogar ein anderes PHP-Skript ausführen , mit dem die Anforderung gestellt wird file_get_conents().

Darryl Hein
quelle
2

Sie sollten besser Nachrichtenwarteschlangen anstelle der empfohlenen Methoden verwenden. Ich bin sicher, dass dies eine bessere Lösung sein wird, obwohl es etwas mehr Arbeit erfordert als nur das Senden einer Anfrage.

mra214
quelle
2

lass mich dir meinen Weg zeigen :)

benötigt 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);
}
user1031143
quelle
1
Dies ist keine reine PHP-Lösung.
Binki
2

Für mich ist die Frage über asynchrone GET - Anforderung ist erschienen , weil ich mit Situation getroffen , als ich tun müssen Hunderte von Anfragen zu erhalten und beschäftigen Ergebnisdaten auf jede Anforderung und jede Anfrage dauert erhebliche Millisekunden auszuführen , dass führt zu Minuten (!) Von total mit einfach ausführen file_get_contents.

In diesem Fall war es ein sehr hilfreicher Kommentar von w_haigh bei php.net zur Funktion http://php.net/manual/en/function.curl-multi-init.php

Hier ist meine aktualisierte und bereinigte Version, in der viele Anfragen gleichzeitig gestellt werden. In meinem Fall entspricht dies dem "asynchronen" Weg. Vielleicht hilft es jemandem!

// Build the multi-curl handle, adding both $ch
$mh = curl_multi_init();

// Build the individual requests, but do not execute them
$chs = [];
$chs['ID0001'] = curl_init('http://webservice.example.com/?method=say&word=Hello');
$chs['ID0002'] = curl_init('http://webservice.example.com/?method=say&word=World');
// $chs[] = ...
foreach ($chs as $ch) {
    curl_setopt_array($ch, [
        CURLOPT_RETURNTRANSFER => true,  // Return requested content as string
        CURLOPT_HEADER => false,         // Don't save returned headers to result
        CURLOPT_CONNECTTIMEOUT => 10,    // Max seconds wait for connect
        CURLOPT_TIMEOUT => 20,           // Max seconds on all of request
        CURLOPT_USERAGENT => 'Robot YetAnotherRobo 1.0',
    ]);

    // Well, with a little more of code you can use POST queries too
    // Also, useful options above can be  CURLOPT_SSL_VERIFYHOST => 0  
    // and  CURLOPT_SSL_VERIFYPEER => false ...

    // Add every $ch to the multi-curl handle
    curl_multi_add_handle($mh, $ch);
}

// Execute all of queries simultaneously, and continue when ALL OF THEM are complete
$running = null;
do {
    curl_multi_exec($mh, $running);
} while ($running);

// Close the handles
foreach ($chs as $ch) {
    curl_multi_remove_handle($mh, $ch);
}
curl_multi_close($mh);

// All of our requests are done, we can now access the results
// With a help of ids we can understand what response was given
// on every concrete our request
$responses = [];
foreach ($chs as $id => $ch) {
    $responses[$id] = curl_multi_getcontent($ch);
    curl_close($ch);
}
unset($chs); // Finita, no more need any curls :-)

print_r($responses); // output results

Es ist einfach, dies neu zu schreiben, um POST oder andere Arten von HTTP (S) -Anfragen oder beliebige Kombinationen davon zu verarbeiten. Und Cookie-Unterstützung, Weiterleitungen, http-auth usw.

FlameStorm
quelle
Ohh .. Ich sehe die Frage, die 2009 erstellt wurde, und ich schreibe meine Antwort im Jahr 2016 :) Aber viele von uns Google PHP werden asynchron und kamen hierher.
FlameStorm
Ja, ich bin auch hierher gekommen, als ich gegoogelt habe. Einige Codierer möchten möglicherweise auch einen Blick in die Guzzle-PHP-Bibliothek werfen, die gleichzeitige und asynchrone Anforderungen unterstützt.
Simon East
1

Versuchen:

//Your Code here
$pid = pcntl_fork();
if ($pid == -1) {
     die('could not fork');
}
else if ($pid)
{
echo("Bye")  
}
else
{
     //Do Post Processing
}

Dies funktioniert NICHT als Apache-Modul. Sie müssen CGI verwenden.

LM.
quelle
1

Ich fand diesen interessanten Link für die asynchrone Verarbeitung (Anfrage anfordern).

Askapache

Darüber hinaus können Sie eine asynchrone Verarbeitung durchführen, indem Sie eine Nachrichtenwarteschlange wie beispielsweise Beanstalkd verwenden.

Alfred
quelle
1

Hier ist eine Anpassung der akzeptierten Antwort zum Ausführen einer einfachen GET-Anforderung.

Wenn der Server eine URL neu schreibt, funktioniert dies nicht. Sie müssen einen voll ausgestatteten http-Client verwenden.

  /**
   * Performs an async get request (doesn't wait for response)
   * Note: One limitation of this approach is it will not work if server does any URL rewriting
   */
  function async_get($url)
  {
      $parts=parse_url($url);

      $fp = fsockopen($parts['host'],
          isset($parts['port'])?$parts['port']:80,
          $errno, $errstr, 30);

      $out = "GET ".$parts['path']." HTTP/1.1\r\n";
      $out.= "Host: ".$parts['host']."\r\n";
      $out.= "Connection: Close\r\n\r\n";
      fwrite($fp, $out);
      fclose($fp);
  }
blak3r
quelle
1

Nur ein paar Korrekturen an den oben genannten Skripten. Das Folgende funktioniert für mich

function curl_request_async($url, $params, $type='GET')
    {
        $post_params = array();
        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);
        echo print_r($parts, TRUE);
        $fp = fsockopen($parts['host'],
            (isset($parts['scheme']) && $parts['scheme'] == 'https')? 443 : 80,
            $errno, $errstr, 30);

        $out = "$type ".$parts['path'] . (isset($parts['query']) ? '?'.$parts['query'] : '') ." 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";
        // Data goes in the request body for a POST request
        if ('POST' == $type && isset($post_string)) $out.= $post_string;
        fwrite($fp, $out);
        fclose($fp);
    }
A23
quelle
Ich habe ein Problem, bei dem das fwrite eine positive Anzahl von Bytes zurückgibt, aber der Skriptendpunkt nicht aufgerufen wird (nicht protokolliert). Es funktioniert nur, wenn ich verwende: while (! Feof ($ fp)) {fgets ($ fp 128); }
Miguel
1

Niemand scheint Guzzle zu erwähnen , einen PHP-HTTP-Client, der das Senden von HTTP-Anforderungen erleichtert. Es kann mit oder ohne arbeiten Curl. Es kann sowohl synchrone als auch asynchrone Anforderungen senden.

$client = new GuzzleHttp\Client();
$promise = $client->requestAsync('GET', 'http://httpbin.org/get');
$promise->then(
    function (ResponseInterface $res) {
        echo $res->getStatusCode() . "\n";
    },
    function (RequestException $e) {
        echo $e->getMessage() . "\n";
        echo $e->getRequest()->getMethod();
    }
);
zstate
quelle
Ja, viele der Antworten in diesem Thread sind ziemlich alt, aber Guzzle ist definitiv die beste Option, die mir 2018 begegnet ist, danke für die Veröffentlichung.
Simon East
0

Basierend auf diesem Thread habe ich dies für mein Codeigniter-Projekt gemacht. Es funktioniert gut. Sie können jede Funktion im Hintergrund bearbeiten lassen.

Ein Controller, der die asynchronen Aufrufe akzeptiert.

class Daemon extends CI_Controller
{
    // Remember to disable CI's csrf-checks for this controller

    function index( )
    {
        ignore_user_abort( 1 );
        try
        {
            if ( strcmp( $_SERVER['REMOTE_ADDR'], $_SERVER['SERVER_ADDR'] ) != 0 && !in_array( $_SERVER['REMOTE_ADDR'], $this->config->item( 'proxy_ips' ) ) )
            {
                log_message( "error", "Daemon called from untrusted IP-address: " . $_SERVER['REMOTE_ADDR'] );
                show_404( '/daemon' );
                return;
            }

            $this->load->library( 'encrypt' );
            $params = unserialize( urldecode( $this->encrypt->decode( $_POST['data'] ) ) );
            unset( $_POST );
            $model = array_shift( $params );
            $method = array_shift( $params );
            $this->load->model( $model );
            if ( call_user_func_array( array( $this->$model, $method ), $params ) === FALSE )
            {
                log_message( "error", "Daemon could not call: " . $model . "::" . $method . "()" );
            }
        }
        catch(Exception $e)
        {
            log_message( "error", "Daemon has error: " . $e->getMessage( ) . $e->getFile( ) . $e->getLine( ) );
        }
    }
}

Und eine Bibliothek, die die asynchronen Aufrufe ausführt

class Daemon
{
    public function execute_background( /* model, method, params */ )
    {
        $ci = &get_instance( );
        // The callback URL (its ourselves)
        $parts = parse_url( $ci->config->item( 'base_url' ) . "/daemon" );
        if ( strcmp( $parts['scheme'], 'https' ) == 0 )
        {
            $port = 443;
            $host = "ssl://" . $parts['host'];
        }
        else 
        {
            $port = 80;
            $host = $parts['host'];
        }
        if ( ( $fp = fsockopen( $host, isset( $parts['port'] ) ? $parts['port'] : $port, $errno, $errstr, 30 ) ) === FALSE )
        {
            throw new Exception( "Internal server error: background process could not be started" );
        }
        $ci->load->library( 'encrypt' );
        $post_string = "data=" . urlencode( $ci->encrypt->encode( serialize( func_get_args( ) ) ) );
        $out = "POST " . $parts['path'] . " HTTP/1.1\r\n";
        $out .= "Host: " . $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";
        $out .= $post_string;
        fwrite( $fp, $out );
        fclose( $fp );
    }
}

Diese Methode kann aufgerufen werden, um jedes model :: method () im 'Hintergrund' zu verarbeiten. Es werden variable Argumente verwendet.

$this->load->library('daemon');
$this->daemon->execute_background( 'model', 'method', $arg1, $arg2, ... );
Patrick Savalle
quelle
0

Vorschlag: Formatieren Sie eine FRAMESET-HTML-Seite, die beispielsweise 9 Frames enthält. Jeder Frame erhält eine andere "Instanz" Ihrer myapp.php-Seite. Parallel dazu werden 9 verschiedene Threads auf dem Webserver ausgeführt.

newbie_dude
quelle
0

Für PHP5.5 + ist mpyw / co die ultimative Lösung. Es funktioniert so, als wäre es tj / co in JavaScript .

Beispiel

Angenommen, Sie möchten die Avatare mehrerer GitHub-Benutzer herunterladen. Die folgenden Schritte sind für jeden Benutzer erforderlich.

  1. Holen Sie sich den Inhalt von http://github.com/mpyw (GET HTML)
  2. Finde <img class="avatar" src="...">und fordere es an (GET IMAGE)

---: Warten auf meine Antwort
...: Warten auf andere Antworten in parallelen Flüssen

Viele berühmte curl_multiSkripte bieten uns bereits die folgenden Abläufe.

        /-----------GET HTML\  /--GET IMAGE.........\
       /                     \/                      \ 
[Start] GET HTML..............----------------GET IMAGE [Finish]
       \                     /\                      /
        \-----GET HTML....../  \-----GET IMAGE....../

Dies ist jedoch nicht effizient genug. Möchten Sie wertlose Wartezeiten reduzieren ...?

        /-----------GET HTML--GET IMAGE\
       /                                \            
[Start] GET HTML----------------GET IMAGE [Finish]
       \                                /
        \-----GET HTML-----GET IMAGE.../

Ja, mit mpyw / co ist es sehr einfach. Weitere Informationen finden Sie auf der Repository-Seite.

mpyw
quelle
-1

Hier ist meine eigene PHP-Funktion, wenn ich POST zu einer bestimmten URL einer beliebigen Seite mache ....

Beispiel: * Nutzung meiner Funktion ...

<?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>
Ich bin ArbZ
quelle
-2

Versuchen Sie diesen Code ....

$chu = curl_init();

curl_setopt($chu, CURLOPT_URL, 'http://www.myapp.com/test.php?someprm=xyz');

curl_setopt($chu, CURLOPT_FRESH_CONNECT, true);
curl_setopt($chu, CURLOPT_TIMEOUT, 1);

curl_exec($chu);
curl_close($chu);

Bitte vergessen Sie nicht, die CURL PHP-Erweiterung zu aktivieren.

Mukesh
quelle
Sie können CURLOPT_TIMEOUT_MSzB 100 Millisekunden einstellen, anstatt CURLOPT_TIMEOUTin Sekunden und mindestens 1 Sekunde - für eine schnellere Ausführung.
Jason Silver
-5

Dies funktioniert gut für mich, leider können Sie die Antwort von Ihrer Anfrage nicht abrufen:

<?php
header("http://mahwebsite.net/myapp.php?var=dsafs");
?>

Es funktioniert sehr schnell, es werden keine rohen TCP-Sockets benötigt :)

D4zk1tty
quelle
Diese Funktion fügt der Antwort einen Header hinzu. Sie sendet keine Header-Anforderung. php.net/manual/bg/function.header.php
Lachezar Todorov