PHP'de nasıl zaman uyumsuz GET isteği yapabilirim?


98

Farklı bir sunucudaki başka bir komut dosyasına basit bir GET isteği yapmak istiyorum. Bunu nasıl yaparım?

Bir durumda, herhangi bir çıktıya ihtiyaç duymadan harici bir komut dosyası istemem gerekiyor.

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

İkinci durumda, metin çıktısını almam gerekiyor.

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

Dürüst olmak gerekirse, bu gerçekten CURL'nin işi olmadığı için CURL ile uğraşmak istemiyorum. Ayrıca PECL uzantılarına sahip olmadığım için http_get'i kullanmak istemiyorum.

Fsockopen işe yarar mı? Öyleyse, dosyanın içeriğini okumadan bunu nasıl yapabilirim? Başka yolu yok mu?

Hepinize teşekkürler

Güncelleme

İlk durumda, betiğin herhangi bir şey döndürmesini beklemek istemediğimi eklemeliyim. Anladığım kadarıyla file_get_contents () sayfanın tamamen yüklenmesini bekleyecek mi?


6
@William: Evet, çoğu soru kendilerinin aynısı olarak kabul edilebilir. 8-) Sanırım yanlış bağlantı
göndermişsiniz


1
Musicfreak'in yayınladığı bağlantıyı göndermek istedim, sekmelerimi karıştırdı ;-)
William Brendel

2
@Richie: Çoğu soru? ;)
Sasha Chedygov

1
Soruyu diğerinden ayırt etmek için yeniden sıraladım, çünkü bir istekte bulunmak istiyorsunuz, yanıtı kullanmakla ilgilenmiyorsunuz (böylece komut dosyasının geri kalanı çalışırken olabilir). Yanılıyorsam geri al!
dbr

Yanıtlar:


52

file_get_contents ne istersen yapacak

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

Düzenleme: Bir GET isteğini başlatmanın ve hemen geri dönmenin bir yolu.

Http://petewarden.typepad.com/searchbrowser/2008/06/how-to-post-an.html adresinden alıntı yapılmıştır

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

Bunun yaptığı şey bir soket açmak, bir alma talebini ateşlemek ve hemen soketi kapatıp geri dönmektir.


6
curl_post_async, bir GET değil, bir POST isteği gönderir.
Vinko Vrsalovic

13
Bu işlevin yanlış adlandırıldığını söylemekte haklı mıyım? Curl kitaplığıyla gerçekten bir ilgisi yok. Fsock_post_async () buna daha çok benziyor
MikeMurko

62
Bu eşzamansız DEĞİLDİR! Özellikle diğer taraftaki sunucu çalışmıyorsa, bu kod parçası 30 saniye boyunca askıda kalacaktır (fsockopen'daki 5. parametre). Ayrıca fwrite'ın çalıştırılması tatlı zamanını alacak (stream_set_timeout ($ fp, $ my_timeout) ile sınırlayabilirsiniz. Yapabileceğiniz en iyi şey, fsockopen'da düşük bir zaman aşımı 0.1 (100ms) ve $ my_timeout'u 100ms'ye ayarlamaktır. Yine de, isteğin zaman aşımına uğrama riskini alıyorsunuz.
Chris Cinelli

4
Bunun eşzamansız ile ilgisi yok. Bu, aldığı kadar senkronize ... Async, bu görev tamamlanırken diğer görevleri yapmak anlamına gelir. Paralel uygulama.
CodeAngry

17
Bu ne zaman uyumsuz ne de bunu çağırarak nasıl cesaret, curl kullanıyor curl_post_asynchatta upvotes ve almak ...
Daniel W.

33

Marquis'in cevabının hem POST hem de GET istekleriyle çalışmasını şu şekilde yapabilirsiniz:

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

2
Bu kullanışlı bir kod parçacığı ve onu burada ve orada kullanıyorum, ancak şimdi aynı şeyi, ancak bir SSL sitesi ile yapmam gerektiğini görüyorum. HTTP / 1.1 türü ve bağlantı noktası dışında değiştirmem gereken bir şey var mı?
Kevin Jhangiani

2
Bunu SSL için kullanmayla ilgili soruya yanıt olarak, bağlantı noktasını 443 olarak değiştirip fsockopen: $ fp = fsockopen ("ssl: //". $ Parts ['ana bilgisayar) içindeki bağlantı noktası adına ssl: // ekleyerek SSL yapabilirsiniz. '],
Michael Dogger

1
"HTTP / 1.1 türü ve bağlantı noktası dışında değiştirmem gereken herhangi bir şey var mı?" - Evet, fsockopen () işlevini ssl://hostnamesadece yerine ana bilgisayar adı ile çağırmalısınız hostname.
Cowlby

22
Bu eşzamansız DEĞİLDİR! Özellikle diğer taraftaki sunucu çalışmıyorsa, bu kod parçası 30 saniye boyunca askıda kalacaktır (fsockopen'daki 5. parametre). Ayrıca fwrite'ın çalıştırılması tatlı zamanını alacak (stream_set_timeout ($ fp, $ my_timeout) ile sınırlayabilirsiniz. Yapabileceğiniz en iyi şey, fsockopen'da düşük bir zaman aşımı 0.1 (100ms) ve $ my_timeout'u 100ms'ye ayarlamaktır. Yine de, isteğin zaman aşımına uğrama riskini alıyorsunuz.
Chris Cinelli

1
GET için İçerik Uzunluğu ayarlanmamalıdır. Belki bazı senaryolarda hataya neden olmaz ama benim durumumda isteğin php betiği olarak adlandırılan tarafından işlenmemesiyle sonuçlandı.
user3285954

13

Güncellemenizle ilgili olarak, tam sayfanın yüklenmesini beklemek istememekle ilgili - HEADaradığınız şeyin bir HTTP isteği olduğunu düşünüyorum ..

get_headers bunu yapmalı - bence sadece başlıkları istiyor, bu yüzden tam sayfa içeriği gönderilmeyecek.

"PHP / Curl: HEAD Request bazı sitelerde uzun sürüyor" , HEADPHP / Curl kullanılarak bir isteğin nasıl yapılacağını açıklar

İsteği tetiklemek istiyor ve komut dosyasını hiç bekletmiyorsanız, çeşitli karmaşıklıkların birkaç yolu vardır.

  • HTTP isteğini bir arka plan işlemi olarak yürütün, php bir arka plan işlemi yürütür - temelde buna benzer bir şey yürütürsünüz "wget -O /dev/null $carefully_escaped_url"- bu platforma özgü olacaktır ve komuttan parametrelerden kaçarken gerçekten dikkatli olmalısınız
  • Arka planda bir PHP betiğini çalıştırmak - temelde UNIX işlem yöntemiyle aynıdır, ancak bir kabuk komutu yerine bir PHP betiğini çalıştırmak
  • Bir veritabanı kullanarak (veya muhtemelen gereğinden fazla olan beanstalkd gibi) bir "iş kuyruğuna" sahip olun. Kuyruğa bir URL eklersiniz ve bir arka plan işlemi veya cron-job rutin olarak yeni işleri kontrol eder ve URL'de istekleri gerçekleştirir

Daha önce düşünmediğim çeşitli ilginç seçenekler için +1
Jasdeep Khalsa

"Bence yalnızca başlıkları istiyor" - Belki, ancak bir belgenin bir HEAD isteğine yanıt olarak tam yanıt gövdesi göndermesini engelleyecek hiçbir şey yoktur. Ve bu yöntemin başlık altında fsock kullanacağını ve tam yanıtı beklemeye (ve okumaya) zorlayacağını varsayıyorum.
hiburn8

6

Yapmıyorsun. PHP, bir URL'yi çağırmanın birçok yolunu sunsa da, istek / yürütme döngüsü başına herhangi bir tür eşzamansız / iş parçacıklı işlem yapmak için kutunun dışında bir destek sunmaz. Bir URL (veya bir SQL deyiminde veya vs.) için bir istek gönderme herhangi bir yöntem beklemek için gidiyor bazı yanıtın tür. Bunu başarmak için yerel makinede çalışan bir tür ikincil sisteme ihtiyacınız olacak ("php iş kuyruğu" için google'da)


1
Burada bir hack var: stackoverflow.com/questions/124462/asynchronous-php-calls (Christian Davén tarafından verilen yanıt) ancak sıranın bunu yapmanın doğru yolu olduğuna katılıyorum.
Chris Cinelli

Sanırım 2009'dan gelen bu cevap artık modası geçmiş. Guzzle PHP kütüphanesi şimdi eşzamanlı ve eşzamansız isteklerini yapmak için desteği vardır.
Simon East

6

PHP kitaplığını iyi test etmenizi tavsiye ederim: 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
}

Guzzle PHP kütüphanesi de eşzamanlı ve eşzamansız isteklerini yapmak için desteği vardır.
Simon East

Guzzle, desteğe sahip olduğunu iddia ediyor, ancak postAsync yöntemini test etmek, eşzamanlı olarak 150 ms ve ardından eşzamansız olarak 2 ms gibi görünüyor. Başarısız bir şekilde düzeltmek için bir saatten fazla zaman harcadım - bunu tavsiye etmem.
Velizar Hristov

4

Linux ortamı kullanıyorsanız, linux curl'yi çağırmak için PHP'nin exec komutunu kullanabilirsiniz. İşte Eşzamansız HTTP gönderisi yapacak örnek bir kod.

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

Bu kod fazladan PHP kitaplığına ihtiyaç duymaz ve http gönderisini 10 milisaniyeden daha kısa sürede tamamlayabilir.


1
bu çok kötü bir fikir: exec çok başarısız: 6/200 müşterisinin ücretli bir rezervasyon için e-posta onayını almayacağını hayal edin ...
HellBaby

Başka bir sunucuda başka bir komut dosyası başlatmak için bir ping'e ihtiyacım olduğu sürece, bu benim için çalıştı. Bunu sadece şu şekilde kullandım: _async_http_post ($ url, ''); Ve bu OVH'nin karşılıklı sunucuları üzerinde çalışıyor ... Bu harika.
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);
}

getstatus()Veya waitSend()veya çağırmanıza izin veren bir nesne döndürmesini sağlayabilirsiniz waitResult(). Bu şekilde, arayan, sonuç olup olmadığını kontrol etmek için bir döngü içinde arayarak tamamen eşzamansız davranış elde edebilir ve değilse, çalışan başka bir göreve devam edebilir. Hmm, şimdi Task
.net'ten php'ye geçmek

3

İlginç bir sorun. Tahminimce diğer sunucuda bazı işlemleri veya eylemleri tetiklemek istiyorsunuz, ancak sonuçların ne olduğu umrunda değil ve komut dosyanızın devam etmesini istemiyorsunuz. Muhtemelen cURL'de bunu gerçekleştirebilecek bir şey vardır, ancak exec()cURL bunu yapamazsa, aramayı yapan sunucuda başka bir komut dosyası çalıştırmak için kullanmayı düşünebilirsiniz . (Tipik olarak insanlar komut dosyası çağrısının sonuçlarını isterler, bu nedenle PHP'nin işlemi tetikleme yeteneğine sahip olup olmadığından emin değilim.) İle istekte bulunan exec()bir wgetveya hatta başka bir PHP betiğini çalıştırabilirsiniz file_get_conents().


2

Önerilen yöntemler yerine Mesaj Kuyruklarını kullanmayı düşünseniz iyi olur. Bir istek göndermekten biraz daha fazla iş gerektirse de, bunun daha iyi bir çözüm olacağına eminim.


2

sana yolumu göstermeme izin ver :)

sunucuda nodej'lerin kurulu olması gerekiyor

(sunucum 1000 https gönderiyor alma isteği sadece 2 saniye sürüyor)

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

1
Bu saf bir PHP çözümü değildir.
binki

2

Yapmam gereken zaman durum ile bir araya geldi yüzünden Benim için asenkron GET isteği hakkında soru karşımıza çıkmaktadır yüzlerce istek , almak ve başa her istekte sonuç verisi ve her istek alır yürütme önemli milisaniye olduğunu dakikaya açar (!) Arasında basit ile toplam yürütme file_get_contents.

Bu durumda php.net'te w_haigh'in http://php.net/manual/en/function.curl-multi-init.php işlevi üzerine çok faydalı bir yorumu oldu.

İşte eşzamanlı olarak birçok istekte bulunmanın yükseltilmiş ve temizlenmiş versiyonu. Benim durumum için "asenkron" yolla eşdeğerdir. Birisine yardımcı olabilir!

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

POST veya diğer HTTP (S) isteklerini veya bunların herhangi bir kombinasyonunu işlemek için bunu yeniden yazmak kolaydır. Ve Çerez desteği, yönlendirmeler, http-kimlik doğrulama vb.


Ohh .. 2009'da oluşturulan soruyu görüyorum ve cevabımı 2016'da yazıyorum :) Ama çoğumuz google php asenkron oluyor ve buraya geldik.
FlameStorm

Evet, Google'da da geldim buraya. Bazı kodlayıcılar , eşzamanlı ve eşzamansız istekler yapma desteği olan Guzzle PHP kitaplığına da bakmak isteyebilir .
Simon East

1

Deneyin:

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

Bu bir apache modülü olarak ÇALIŞMAYACAKTIR, CGI kullanmanız gerekir.


1

Eşzamansız işlem yapmak için bu ilginç bağlantıyı buldum (istek alma).

askapache

Ayrıca, beanstalkd gibi bir mesaj kuyruğu kullanarak eşzamansız işlem yapabilirsiniz.


1

İşte basit bir GET isteği gerçekleştirmek için kabul edilen yanıtın bir uyarlaması.

Unutulmaması gereken bir şey, sunucu herhangi bir url yeniden yazıyorsa, bu işe yaramayacaktır. Daha tam özellikli bir http istemcisi kullanmanız gerekecek.

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

1

Yukarıda yayınlanan komut dosyalarında sadece birkaç düzeltme. Aşağıdakiler benim için çalışıyor

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

Fwrite'ın pozitif bir bayt sayısı döndürdüğü, ancak komut dosyasının uç noktasının çağrılmadığı (günlüğe kaydetmediği) bir sorun yaşıyorum .. yalnızca şunu kullandığımda çalışıyor: while (! Feof ($ fp)) {fgets ($ fp , 128); }
Miguel

1

Hiç kimse HTTP isteklerini göndermeyi kolaylaştıran bir PHP HTTP istemcisi olan Guzzle'dan bahsetmiyor gibi görünüyor . İle veya onsuz çalışabilir Curl. Hem eşzamanlı hem de eşzamansız istekler gönderebilir.

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

Evet, bu konudaki cevapların çoğu oldukça eski, ancak Guzzle kesinlikle 2018'de karşılaştığım en iyi seçenek, gönderdiğiniz için teşekkürler.
Simon East

0

Bu iş parçacığına dayanarak bunu kod işaretleyici projem için yaptım. Gayet iyi çalışıyor. Arka planda herhangi bir işlevi işleyebilirsiniz.

Eşzamansız çağrıları kabul eden bir denetleyici.

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

Ve eşzamansız çağrıları yapan bir kütüphane

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

Bu yöntem, 'arka planda' herhangi bir model :: method () işlemek için çağrılabilir. Değişken argümanlar kullanır.

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

0

Öneri: Diyelim ki içinde 9 çerçeve içeren bir FRAMESET HTML sayfasını biçimlendirin. Her çerçeve, myapp.php sayfanızın farklı bir "örneğini" ALACAKTIR. Web sunucusunda paralel olarak çalışan 9 farklı iş parçacığı olacaktır.


0

PHP5.5 + için mpyw / co nihai çözümdür. JavaScript'te tj / co gibi çalışır .

Misal

Belirtilen birden çok GitHub kullanıcısının avatarını indirmek istediğinizi varsayalım. Her kullanıcı için aşağıdaki adımlar gereklidir.

  1. Http://github.com/mpyw (HTML GET) içeriğini alın
  2. Bulun <img class="avatar" src="...">ve isteyin (GÖRÜNTÜ ALIN)

---: Yanıtımı bekliyorum
...: Paralel akışlarda diğer yanıtı bekliyorum

Birçok ünlü curl_multitabanlı komut dosyası bize aşağıdaki akışları zaten sağlıyor.

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

Ancak bu yeterince verimli değil. Değersiz bekleme sürelerini azaltmak ister misiniz ...?

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

Evet, mpyw / co ile çok kolay. Daha fazla ayrıntı için bilgi havuzu sayfasını ziyaret edin.


-1

Herhangi bir sayfanın belirli bir URL'sine POST yaptığımda kendi PHP işlevim burada ...

Örnek: * İşlevimin kullanımı ...

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

-2

Bu kodu deneyin ....

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

Lütfen CURL php uzantısını etkinleştirmeyi unutmayın.


Daha hızlı yürütme için CURLOPT_TIMEOUT_MSörneğin 100 milisaniye yerine CURLOPT_TIMEOUTsaniye cinsinden ve en az 1 saniye olan 100 milisaniye ayarlayabilirsiniz .
Jason Silver

-5

Bu benim için iyi çalışıyor, maalesef isteğinizin yanıtını alamazsınız:

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

Çok hızlı çalışıyor, ham tcp soketlerine gerek yok :)


Bu işlev yanıta bir başlık ekler ... başlık isteği göndermez. php.net/manual/bg/function.header.php
Lachezar Todorov
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.