Bagaimana cara membuat permintaan GET asinkron di PHP?

97

Saya ingin membuat permintaan GET sederhana ke skrip lain di server berbeda. Bagaimana saya melakukan ini?

Dalam satu kasus, saya hanya perlu meminta skrip eksternal tanpa memerlukan keluaran apa pun.

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

Dalam kasus kedua, saya perlu mendapatkan keluaran teks.

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

Sejujurnya, saya tidak ingin main-main dengan CURL karena ini bukanlah tugas CURL. Saya juga tidak ingin menggunakan http_get karena saya tidak memiliki ekstensi PECL.

Apakah fsockopen akan berhasil? Jika ya, bagaimana cara melakukannya tanpa membaca konten file? Apakah tidak ada cara lain?

Terima kasih semuanya

Memperbarui

Saya harus menambahkan, dalam kasus pertama, saya tidak ingin menunggu skrip mengembalikan apa pun. Seperti yang saya pahami file_get_contents () akan menunggu halaman dimuat sepenuhnya dll?

Abs
sumber
6
@William: Ya, sebagian besar pertanyaan dapat dianggap duplikat persis dari pertanyaan itu sendiri. 8-) Saya pikir Anda memposting tautan yang salah ...
RichieHindle
Duplikat: stackoverflow.com/questions/959063/…
Sasha Chedygov
1
Saya bermaksud untuk memposting tautan musicfreak yang diposting, mencampurkan tab saya ;-)
William Brendel
2
@Richie: Kebanyakan pertanyaan? ;)
Sasha Chedygov
1
Saya memberi judul ulang pertanyaan untuk membedakannya dari yang lain, karena sepertinya Anda ingin membuat permintaan tidak peduli tentang menggunakan respons (sehingga itu bisa terjadi saat skrip lainnya berjalan). Kembalikan jika saya salah!
dbr

Jawaban:

52

file_get_contents akan melakukan apa yang kamu inginkan

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

Edit: Salah satu cara untuk menjalankan permintaan GET dan segera kembali.

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

Apa yang dilakukannya adalah membuka soket, mematikan permintaan get, dan segera menutup soket dan mengembalikannya.

Marquis Wang
sumber
6
curl_post_async mengirimkan permintaan POST, bukan GET.
Vinko Vrsalovic
13
Apakah saya benar mengatakan bahwa fungsi ini dinamai dengan tidak benar? Ini benar-benar tidak ada hubungannya dengan perpustakaan curl. Ini fsock_post_async () lebih seperti itu
MikeMurko
61
Ini BUKAN asinkron! Khususnya jika server di sisi lain sedang down, bagian kode ini akan hang selama 30 detik (parameter ke-5 di fsockopen). Juga fwrite akan mengambil waktu yang tepat untuk mengeksekusi (yang dapat Anda batasi dengan stream_set_timeout ($ fp, $ my_timeout). Hal terbaik yang dapat Anda lakukan adalah menyetel batas waktu rendah pada fsockopen menjadi 0,1 (100ms) dan $ my_timeout menjadi 100ms Anda berisiko, bahwa permintaan waktu habis.
Chris Cinelli
4
Ini tidak ada hubungannya dengan async. Ini sinkron seperti yang didapat ... Async berarti melakukan tugas lain saat tugas ini sedang diselesaikan. Ini eksekusi paralel.
CodeAngry
17
Ini bukan async juga tidak menggunakan curl, bagaimana Anda berani menyebutnya curl_post_asyncdan mendapatkan suara positif ...
Daniel
33

Ini adalah cara membuat jawaban Marquis berfungsi dengan permintaan POST dan GET:

  // $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
sumber
2
Ini adalah potongan kode yang berguna, dan saya telah menggunakannya di sana-sini, tetapi sekarang saya menemukan bahwa saya perlu melakukan hal yang sama, tetapi dengan situs SSL. Apakah ada yang perlu saya ubah selain tipe HTTP / 1.1 dan porta?
Kevin Jhangiani
2
Dalam Menanggapi pertanyaan tentang penggunaan ini untuk SSL, Anda dapat membuatnya menjadi SSL dengan mengubah port menjadi 443 dan menambahkan ssl: // ke nama port di fsockopen: $ fp = fsockopen ("ssl: //". $ Parts ['host '],
Michael Dogger
1
"Apakah ada yang perlu saya ubah selain jenis HTTP / 1.1 dan porta?" - Ya, Anda harus memanggil fsockopen () dengan nama host, ssl://hostnamebukan hanya hostname.
Cowlby
22
Ini BUKAN asinkron! Khususnya jika server di sisi lain sedang down, bagian kode ini akan hang selama 30 detik (parameter ke-5 di fsockopen). Juga fwrite akan mengambil waktu yang tepat untuk mengeksekusi (yang dapat Anda batasi dengan stream_set_timeout ($ fp, $ my_timeout). Hal terbaik yang dapat Anda lakukan adalah menyetel batas waktu rendah pada fsockopen menjadi 0,1 (100ms) dan $ my_timeout menjadi 100ms Anda berisiko, bahwa permintaan waktu habis.
Chris Cinelli
1
Panjang Konten tidak boleh disetel untuk GET. Mungkin pada beberapa skenario tidak menyebabkan error tetapi pada kasus saya mengakibatkan request tidak diproses dengan script php.
pengguna3285954
13

Mengenai pembaruan Anda, tentang tidak ingin menunggu halaman penuh dimuat - menurut saya HEADpermintaan HTTP adalah yang Anda cari ..

get_headers harus melakukan ini - Saya pikir itu hanya meminta header, jadi tidak akan dikirimi konten halaman penuh.

"PHP / Curl: HEAD Request membutuhkan waktu lama di beberapa situs" menjelaskan cara melakukan HEADpermintaan menggunakan PHP / Curl

Jika Anda ingin memicu permintaan, dan tidak menahan skrip sama sekali, ada beberapa cara, dengan berbagai kerumitan ..

  • Jalankan permintaan HTTP sebagai proses latar belakang, php jalankan proses latar belakang - pada dasarnya Anda akan menjalankan sesuatu seperti "wget -O /dev/null $carefully_escaped_url"- ini akan menjadi platform khusus, dan Anda harus benar - benar berhati-hati dalam meng-escape parameter ke perintah
  • Menjalankan skrip PHP di latar belakang - pada dasarnya sama dengan metode proses UNIX, tetapi mengeksekusi skrip PHP daripada perintah shell
  • Memiliki "antrian pekerjaan", menggunakan database (atau sesuatu seperti beanstalkd yang mungkin berlebihan). Anda menambahkan URL ke antrian, dan proses latar belakang atau cron-job secara rutin memeriksa pekerjaan baru dan melakukan permintaan pada URL
dbr
sumber
1 untuk berbagai opsi menarik yang belum pernah saya pikirkan sebelumnya
Jasdeep Khalsa
"Saya pikir ini hanya meminta header" - Mungkin, tetapi tidak ada yang menghentikan dokumen agar tidak mengirimkan isi respons lengkap sebagai respons atas permintaan HEAD. Dan saya berasumsi metode ini akan menggunakan fsock di bawah tenda dan memaksanya untuk menunggu (dan membaca) respons penuh.
hiburn8
6

Kamu tidak. Meskipun PHP menawarkan banyak cara untuk memanggil URL, PHP tidak menawarkan dukungan out of the box untuk melakukan segala jenis pemrosesan asinkron / berulir per siklus permintaan / eksekusi. Metode apa pun yang mengirim permintaan untuk URL (atau pernyataan SQL, atau dll.) Akan menunggu beberapa jenis respons. Anda akan membutuhkan semacam sistem sekunder yang berjalan di mesin lokal untuk mencapai ini (cari di google untuk "antrian pekerjaan php")

Alan Storm
sumber
1
Ada peretasan di sini: stackoverflow.com/questions/124462/asynchronous-php-calls (jawaban oleh Christian Davén) tetapi saya setuju bahwa antrean adalah cara yang tepat untuk melakukannya.
Chris Cinelli
Saya pikir jawaban dari tahun 2009 ini sudah ketinggalan zaman. The membuang waktu PHP perpustakaan sekarang memiliki dukungan untuk melakukan permintaan bersamaan dan asynchronous.
Simon East
6

Saya akan merekomendasikan Anda perpustakaan PHP yang teruji dengan baik: 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
sumber
The membuang waktu PHP perpustakaan juga memiliki dukungan untuk melakukan permintaan bersamaan dan asynchronous.
Simon East
Guzzle mengklaim bahwa ia memiliki dukungan, tetapi pengujian metode postAsync-nya terlihat seperti 150 md secara sinkron, dan kemudian 2 md secara asinkron. Saya telah menghabiskan lebih dari satu jam mencoba memperbaikinya tanpa hasil - tidak akan merekomendasikannya.
Velizar Hristov
4

Jika Anda menggunakan lingkungan Linux, Anda dapat menggunakan perintah exec PHP untuk menjalankan linux curl. Berikut adalah contoh kode, yang akan membuat postingan HTTP Asynchronous.

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

Kode ini tidak memerlukan libs PHP tambahan dan dapat menyelesaikan posting http dalam waktu kurang dari 10 milidetik.

Orang asing
sumber
1
ini adalah ide yang sangat buruk: eksekutif gagal banyak: bayangkan bahwa klien 6/200 tidak akan mendapatkan konfirmasi email mereka untuk pemesanan yang dibayar ...
HellBaby
Ini berhasil untuk saya, sejauh saya hanya perlu ping untuk memulai skrip lain di server lain. Saya hanya menggunakannya seperti itu: _async_http_post ($ url, ''); Dan ini bekerja pada server OVH yang saling menguntungkan ... Bagus sekali.
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
sumber
Anda bisa membuatnya mengembalikan objek yang memungkinkan Anda memanggil getstatus()atau waitSend()atau waitResult(). Dengan begitu, pemanggil bisa mendapatkan perilaku asinkron sepenuhnya dengan memanggil dalam satu putaran untuk memeriksa apakah ada hasil dan, jika tidak, melanjutkan ke tugas lain apa pun yang sedang berjalan. Hmm, sekarang saya ingin melakukan port Taskdari .net ke php…
binki
3

Masalah yang menarik. Saya menduga Anda hanya ingin memicu beberapa proses atau tindakan di server lain, tetapi tidak peduli apa hasilnya dan ingin skrip Anda melanjutkan. Mungkin ada sesuatu di cURL yang dapat membuat ini terjadi, tetapi Anda mungkin ingin mempertimbangkan exec()untuk menggunakan skrip lain di server yang melakukan panggilan jika cURL tidak dapat melakukannya. (Biasanya orang menginginkan hasil dari panggilan skrip jadi saya tidak yakin apakah PHP memiliki kemampuan untuk hanya memicu proses.) Dengan exec()Anda dapat menjalankan wgetatau bahkan skrip PHP lain yang membuat permintaan dengan file_get_conents().

Darryl Hein
sumber
2

Anda sebaiknya mempertimbangkan menggunakan Antrean Pesan daripada metode yang disarankan. Saya yakin ini akan menjadi solusi yang lebih baik, meskipun membutuhkan lebih banyak pekerjaan daripada hanya mengirim permintaan.

mra214
sumber
2

biarkan saya menunjukkan jalan saya :)

membutuhkan nodejs yang diinstal di server

(server saya mengirim 1000 https mendapatkan permintaan hanya membutuhkan waktu 2 detik)

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);
}
pengguna1031143
sumber
1
Ini bukan solusi PHP murni.
binki
2

Bagi saya pertanyaan tentang permintaan GET asinkron muncul karena saya bertemu dengan situasi ketika saya perlu melakukan ratusan permintaan , mendapatkan dan menangani data hasil pada setiap permintaan dan setiap permintaan membutuhkan milidetik yang signifikan dari eksekusi yang mengarah ke menit (!) total mengeksekusi dengan sederhana file_get_contents.

Dalam hal ini, komentar w_haigh di php.net sangat membantu tentang fungsi http://php.net/manual/en/function.curl-multi-init.php

Jadi, inilah versi saya yang ditingkatkan dan dibersihkan untuk membuat banyak permintaan secara bersamaan. Untuk kasus saya, ini setara dengan cara "asynchronous". Mungkin itu membantu seseorang!

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

Sangat mudah untuk menulis ulang ini untuk menangani POST atau jenis permintaan HTTP (S) lain atau kombinasinya. Dan dukungan Cookie, pengalihan, http-auth, dll.

FlameStorm
sumber
Ohh .. Saya melihat pertanyaan dibuat pada tahun 2009, dan saya menulis jawaban saya pada tahun 2016 :) Tapi banyak dari kita google php mendapatkan asynchronous dan datang ke sini.
FlameStorm
Ya saya juga datang ke sini saat Googling. Beberapa pembuat kode mungkin juga ingin melihat ke pustaka PHP Guzzle yang memiliki dukungan untuk melakukan permintaan bersamaan dan asinkron.
Simon East
1

Mencoba:

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

Ini TIDAK akan berfungsi sebagai modul apache, Anda harus menggunakan CGI.

LM.
sumber
1

Saya menemukan tautan menarik ini untuk melakukan pemrosesan asinkron (mendapatkan permintaan).

askapache

Selanjutnya Anda dapat melakukan pemrosesan asinkron dengan menggunakan antrian pesan seperti misalnya beanstalkd.

Alfred
sumber
1

Berikut adalah adaptasi dari jawaban yang diterima untuk melakukan permintaan GET sederhana.

Satu hal yang perlu diperhatikan jika server melakukan penulisan ulang url, ini tidak akan berfungsi. Anda harus menggunakan klien http berfitur lengkap.

  /**
   * 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
sumber
1

Hanya sedikit koreksi pada skrip yang diposting di atas. Berikut ini bekerja untuk saya

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
sumber
Saya mengalami masalah, di mana fwrite mengembalikan sejumlah byte positif, tetapi titik akhir skrip tidak dipanggil (bukan logging) .. ini hanya berfungsi ketika saya menggunakan: while (! Feof ($ fp)) {fgets ($ fp , 128); }
Miguel
1

Sepertinya tidak ada yang menyebutkan Guzzle , yang merupakan klien HTTP PHP yang memudahkan untuk mengirim permintaan HTTP. Itu bisa bekerja dengan atau tanpa Curl. Itu dapat mengirim permintaan sinkron dan asinkron.

$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
sumber
Ya, banyak jawaban di utas ini sudah cukup lama, tetapi Guzzle jelas merupakan pilihan terbaik yang saya temui pada tahun 2018, terima kasih telah memposting.
Simon East
0

Berdasarkan utas ini saya membuat ini untuk proyek codeigniter saya. Ini bekerja dengan baik. Anda dapat memiliki fungsi apa pun yang diproses di latar belakang.

Pengontrol yang menerima panggilan async.

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

Dan perpustakaan yang melakukan panggilan asinkron

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

Metode ini bisa dipanggil untuk memproses model :: method () di 'background'. Ini menggunakan argumen variabel.

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

Saran: format halaman HTML FRAMESET yang berisi, katakanlah, 9 frame di dalamnya. Setiap frame akan MENDAPATKAN "contoh" yang berbeda dari halaman myapp.php Anda. Akan ada 9 utas berbeda yang berjalan di server Web, secara paralel.

newbie_dude
sumber
0

Untuk PHP5.5 +, mpyw / co adalah solusi terbaik. Ia bekerja seolah-olah itu adalah tj / co dalam JavaScript.

Contoh

Asumsikan bahwa Anda ingin mengunduh beberapa avatar pengguna GitHub tertentu. Langkah-langkah berikut diperlukan untuk setiap pengguna.

  1. Dapatkan konten http://github.com/mpyw (DAPATKAN HTML)
  2. Temukan <img class="avatar" src="...">dan minta (DAPATKAN GAMBAR)

---: Menunggu tanggapan saya
...: Menunggu tanggapan lain secara paralel

Banyak curl_multiskrip berbasis terkenal sudah memberi kita aliran berikut.

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

Namun, ini tidak cukup efisien. Apakah Anda ingin mengurangi waktu tunggu yang tidak berguna ...?

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

Ya, sangat mudah dengan mpyw / co. Untuk lebih jelasnya, kunjungi halaman repositori.

mpyw
sumber
-1

Ini adalah fungsi PHP saya sendiri ketika saya melakukan POST ke URL tertentu dari halaman mana pun ....

Contoh: * penggunaan Fungsi saya ...

<?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>
saya ArbZ
sumber
-2

Coba kode ini ....

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

Harap jangan lupa untuk mengaktifkan ekstensi php CURL.

Mukesh
sumber
Anda dapat menyetel CURLOPT_TIMEOUT_MSmisalnya 100 milidetik, bukan CURLOPT_TIMEOUTdalam hitungan detik dan memiliki waktu minimal 1 detik - untuk eksekusi lebih cepat.
Jason Silver
-5

Ini berfungsi dengan baik untuk saya, sayangnya Anda tidak dapat mengambil respons dari permintaan Anda:

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

Ini bekerja sangat cepat, tidak perlu soket tcp mentah :)

D4zk1tty
sumber
Fungsi ini menambahkan tajuk ke respons ... itu tidak mengirim permintaan tajuk. php.net/manual/bg/function.header.php
Lachezar Todorov