PHP에서 비동기 GET 요청을 어떻게합니까?


97

다른 서버의 다른 스크립트에 간단한 GET 요청을 만들고 싶습니다. 어떻게해야합니까?

어떤 경우에는 출력없이 외부 스크립트를 요청하기 만하면됩니다.

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

두 번째 경우에는 텍스트 출력이 필요합니다.

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

솔직히 말해서 CURL이 실제로 CURL의 일이 아니기 때문에 CURL을 엉망으로 만들고 싶지 않습니다. 또한 PECL 확장이 없기 때문에 http_get을 사용하고 싶지 않습니다.

fsockopen이 작동할까요? 그렇다면 파일 내용을 읽지 않고 어떻게해야합니까? 다른 방법은 없나요?

모두 감사합니다

최신 정보

첫 번째 경우 스크립트가 아무것도 반환 할 때까지 기다릴 필요가 없습니다. 내가 이해했듯이 file_get_contents ()는 페이지가 완전히로드 될 때까지 기다릴 것입니다.


6
@William : 예, 대부분의 질문은 자신과 정확히 중복되는 것으로 간주 될 수 있습니다. 8) 당신이 잘못된 링크 ... 게시 생각
RichieHindle


1
나는 링크를 게시하려고했다 musicfreak 게시, 내 탭을 혼합 ;-)
William Brendel

2
@Richie : 대부분의 질문? ;)
Sasha Chedygov

1
다른 것과 구별하기 위해 질문의 제목을 변경했습니다. 요청을하고 싶은 것 같기 때문에 응답 사용에 신경 쓰지 않습니다 (나머지 스크립트가 실행될 때 발생할 수 있음). 내가 틀렸다면 되돌 리세요!
dbr

답변:


52

file_get_contents 당신이 원하는 것을 할 것입니다

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

편집 : GET 요청을 시작하고 즉시 반환하는 한 가지 방법입니다.

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

이것이하는 일은 소켓을 열고 get 요청을 실행 한 다음 즉시 소켓을 닫고 반환하는 것입니다.


6
curl_post_async는 GET이 아닌 POST 요청을 보냅니다.
Vinko Vrsalovic

13
이 함수의 이름이 부적절하다고 말하는 것이 맞습니까? curl 라이브러리와는 실제로 관련이 없습니다. 그것은 더 좋아 fsock_post_async ()입니다
MikeMurko

61
이것은 비동기가 아닙니다! 특히 다른 쪽의 서버가 다운 된 경우이 코드는 30 초 동안 중단됩니다 (fsockopen의 5 번째 매개 변수). 또한 fwrite는 실행하는 데 시간이 많이 걸립니다 (stream_set_timeout ($ fp, $ my_timeout)으로 제한 할 수 있습니다. 가장 좋은 방법은 fsockopen에서 낮은 시간 제한을 0.1 (100ms)로, $ my_timeout을 100ms로 설정하는 것입니다) .하지만 요청 시간이 초과 될 위험이 있습니다.
Chris Cinelli

4
이것은 비동기와 관련이 없습니다. 이것은 동기화됩니다. 비동기는이 작업이 완료되는 동안 다른 작업을 수행하는 것을 의미합니다. 병렬 실행입니다.
CodeAngry 2013 년

17
이것은 어느 비동기도 아니고 당신이 그것을 호출 감히 어떻게 컬을 사용하고 curl_post_async도 upvotes을 얻을 ...
다니엘 W.

33

이것은 Marquis의 답변이 POST 및 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);
  }

2
이것은 편리한 코드 스 니펫이며 여기저기서 사용하고 있지만 이제는 SSL 사이트를 사용하여 동일한 작업을 수행해야한다는 것을 알게되었습니다. HTTP / 1.1 유형 및 포트 외에 변경해야 할 사항이 있습니까?
Kevin Jhangiani 2011

2
SSL에 이것을 사용하는 것에 대한 질문에 대한 응답으로 포트를 443으로 변경하고 ssl : //을 fsockopen의 포트 이름에 추가하여 SSL로 만들 수 있습니다. $ fp = fsockopen ( "ssl : //". $ parts [ 'host ']
마이클 닷져

1
"HTTP / 1.1 유형 및 포트 외에 변경해야 할 사항이 있습니까?" -예, ssl://hostname대신 호스트 이름으로 fsockopen ()을 호출해야합니다 hostname.
Cowlby

22
이것은 비동기가 아닙니다! 특히 다른 쪽의 서버가 다운 된 경우이 코드는 30 초 동안 중단됩니다 (fsockopen의 5 번째 매개 변수). 또한 fwrite는 실행하는 데 시간이 많이 걸립니다 (stream_set_timeout ($ fp, $ my_timeout)으로 제한 할 수 있습니다. 가장 좋은 방법은 fsockopen에서 낮은 시간 제한을 0.1 (100ms)로, $ my_timeout을 100ms로 설정하는 것입니다) .하지만 요청 시간이 초과 될 위험이 있습니다.
Chris Cinelli

1
GET에 대해 Content-Length를 설정하면 안됩니다. 일부 시나리오에서는 오류가 발생하지 않지만 제 경우에는 호출 된 php 스크립트에 의해 요청이 처리되지 않을 수 있습니다.
user3285954

13

업데이트와 관련하여 전체 페이지가로드 될 때까지 기다리지 않고 HTTP HEAD요청이 필요한 것 같습니다.

get_headers 는이 작업을 수행해야합니다. 헤더 만 요청하므로 전체 페이지 콘텐츠가 전송되지 않습니다.

"PHP / Curl : 일부 사이트에서 HEAD 요청이 오래 걸립니다"HEADPHP / Curl을 사용하여 요청 을 수행하는 방법을 설명합니다.

요청을 트리거하고 스크립트를 전혀 유지하지 않으려는 경우 다양한 복잡성의 몇 가지 방법이 있습니다.

  • HTTP 요청을 백그라운드 프로세스로 실행하고 , PHP는 백그라운드 프로세스를 실행합니다. 기본적으로 다음과 같은 것을 실행합니다. "wget -O /dev/null $carefully_escaped_url"이는 플랫폼에 따라 다르며 매개 변수를 명령으로 이스케이프 하는 데 매우 주의해야합니다.
  • 백그라운드에서 PHP 스크립트 실행 -기본적으로 UNIX 프로세스 방법과 동일하지만 쉘 명령이 아닌 PHP 스크립트 실행
  • 데이터베이스 (또는 과잉 일 가능성이있는 beanstalkd 와 같은 것)를 사용하여 "작업 대기열"을 만드십시오 . 대기열에 URL을 추가하면 백그라운드 프로세스 또는 cron-job이 정기적으로 새 작업을 확인하고 URL에 대한 요청을 수행합니다.

내가 전에 생각하지으므로 다양한 흥미로운 옵션에 대한 한
Jasdeep Khalsa

"헤더 만 요청한다고 생각합니다."-아마도 문서가 HEAD 요청에 대한 응답으로 전체 응답 본문을 보내는 것을 막을 방법이 없습니다. 그리고 나는이 방법이 후드 아래에서 fsock을 사용하고 전체 응답을 기다리거나 읽도록 강요한다고 가정합니다.
hiburn8

6

당신은하지 않습니다. PHP는 URL을 호출하는 많은 방법을 제공하지만 요청 / 실행주기마다 모든 종류의 비동기 / 스레드 처리를 수행하는 즉시 지원을 제공하지 않습니다. 의 URL (또는 SQL 문, 또는 등)에 대한 요청을 보내는 모든 방법을 기다릴 것입니다 어떤 반응의 종류. 이를 위해서는 로컬 컴퓨터에서 실행되는 일종의 보조 시스템이 필요합니다 ( "php 작업 대기열"에 대한 Google 검색).


1
여기에 해킹이 있습니다 : stackoverflow.com/questions/124462/asynchronous-php-calls (Christian Davén의 답변) 그러나 대기열이 올바른 방법이라는 데 동의합니다.
Chris Cinelli 2012 년

2009 년의이 답변은 이제 구식이라고 생각합니다. 목구멍 PHP 라이브러리는 현재 동시 및 비동기 요청을 수행하기위한 지원을하고있다.
사이먼 이스트

6

잘 테스트 된 PHP 라이브러리를 추천합니다. 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
}

목구멍 PHP 라이브러리는 또한 동시 및 비동기 요청을 수행하기위한 지원을하고있다.
사이먼 이스트

Guzzle은 지원이 있다고 주장하지만 postAsync 메서드를 테스트하는 것은 동 기적으로 150ms를 수행 한 다음 비동기 적으로 2ms를 수행하는 것처럼 보입니다. 나는 성공하지 않고 그것을 고치기 위해 한 시간 이상을 보냈다. 추천하지 않을 것이다.
Velizar Hristov

4

Linux 환경을 사용하는 경우 PHP의 exec 명령을 사용하여 linux curl을 호출 할 수 있습니다. 다음은 비동기 HTTP 게시물을 만드는 샘플 코드입니다.

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

이 코드는 추가 PHP 라이브러리가 필요하지 않으며 10 밀리 초 이내에 http 게시물을 완료 할 수 있습니다.


1
이것은 매우 나쁜 생각입니다 : 간부는 많은 실패 2백분의 6 클라이언트가 지불하고 살만한 예약에 대한 이메일 확인을받지 않습니다 상상 ...
HellBaby

이것은 다른 서버에서 다른 스크립트를 시작하기 위해 핑이 필요한 한 나를 위해 일했습니다. 방금 다음과 같이 사용했습니다. _async_http_post ($ url, ''); 그리고 이것은 OVH 상호 화 된 서버에서 작동하고 있습니다.
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()또는 waitSend()또는 waitResult(). 이렇게하면 호출자는 루프를 호출하여 결과가 있는지 확인하고 그렇지 않은 경우 실행중인 다른 작업을 계속하여 완전히 비동기 동작을 얻을 수 있습니다. 흠, 이제 Task.net에서 php 로 포팅하고 싶습니다 …
binki

3

흥미로운 문제입니다. 다른 서버에서 일부 프로세스 또는 작업을 트리거하고 싶지만 결과가 무엇인지 상관하지 않고 스크립트가 계속되기를 원한다고 생각합니다. cURL에 이런 일이 발생할 수있는 무언가가있을 수 있지만 cURL이이 exec()를 수행 할 수없는 경우 호출을 수행하는 서버에서 다른 스크립트를 실행 하는 데 사용 하는 것을 고려할 수 있습니다. (일반적으로 사람들은 스크립트 호출의 결과를 원하므로 PHP가 프로세스를 트리거하는 기능이 있는지 확실하지 않습니다.) 을 사용하여 요청을 만드는 다른 PHP 스크립트를 exec()실행할 수 있습니다 .wgetfile_get_conents()


2

권장되는 방법 대신 메시지 큐를 사용하는 것이 좋습니다. 요청을 보내는 것보다 약간 더 많은 작업이 필요하지만 이것이 더 나은 해결책이 될 것이라고 확신합니다.


2

내 방식을 보여 드리겠습니다 :)

서버에 설치된 nodejs 필요

(내 서버는 1000 개의 https 요청을 보내는데 2 초 밖에 걸리지 않습니다)

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
이것은 순수한 PHP 솔루션이 아닙니다.
binki 16.10.14

2

나에게 비동기 GET 요청에 대한 질문은 수백 개의 요청 을 수행 하고 모든 요청 에 대해 결과 데이터를 가져오고 처리 해야하는 상황을 만났기 때문에 나타납니다 . 모든 요청 은 실행 하는 데 상당한 밀리 초가 소요 되어 몇 분 (!) 간단한 총 실행file_get_contents .

이 경우 함수 http://php.net/manual/en/function.curl-multi-init.php의 php.net에서 w_haigh 에 대한 매우 유용한 주석이었습니다 .

그래서 여기에 많은 요청을 동시에 만드는 업그레이드되고 정리 된 버전이 있습니다. 제 경우에는 "비동기"방식과 동일합니다. 누군가에게 도움이 될 수 있습니다!

// 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 또는 다른 유형의 HTTP (S) 요청 또는 이들의 조합을 처리하기 위해이를 다시 작성하는 것은 쉽습니다. 그리고 쿠키 지원, 리디렉션, http-auth 등


오 .. 2009 년에 만든 질문을보고 2016 년에 제 답변을 씁니다. :)하지만 많은 Google PHP가 비 동기화 되어 여기에 왔습니다.
FlameStorm

예, 인터넷 검색을 할 때도 여기에 왔습니다. 일부 코더는 동시 및 비동기 요청을 지원 하는 Guzzle PHP 라이브러리 를 살펴보고 싶을 수도 있습니다 .
사이먼 이스트

1

시험:

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

이것은 아파치 모듈로 작동하지 않습니다. CGI를 사용해야합니다.


1

비동기 처리 (요청 받기)를 수행하는 흥미로운 링크를 찾았습니다.

Askapache

또한 예를 들어 beanstalkd와 같은 메시지 대기열을 사용하여 비동기 처리를 할 수 있습니다.


1

다음은 간단한 GET 요청을 수행하기 위해 허용 된 답변을 수정 한 것입니다.

서버가 URL 재 작성을 수행하는 경우주의해야 할 사항은 작동하지 않습니다. 보다 완전한 기능을 갖춘 http 클라이언트를 사용해야합니다.

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

위에 게시 된 스크립트에 대한 몇 가지 수정 사항입니다. 다음은 나를 위해 일하고 있습니다.

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가 양의 바이트를 반환하지만 스크립트 끝 점이 호출되지 않습니다 (로깅되지 않음) .. 다음을 사용할 때만 작동합니다. while (! feof ($ fp)) {fgets ($ fp , 128); }
Miguel

1

HTTP 요청을 쉽게 보낼 수있는 PHP HTTP 클라이언트 인 Guzzle 을 언급하는 사람은 아무도 없습니다 . 를 사용하거나 사용하지 않고 작동 할 수 있습니다 Curl. 동기 및 비동기 요청을 모두 보낼 수 있습니다.

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

예,이 스레드의 많은 답변은 꽤 오래되었지만 Guzzle은 2018 년에 제가 만난 최고의 옵션입니다. 게시 해 주셔서 감사합니다.
Simon East

0

이 스레드를 기반으로 codeigniter 프로젝트를 위해 이것을 만들었습니다. 잘 작동합니다. 백그라운드에서 모든 기능을 처리 할 수 ​​있습니다.

비동기 호출을 수락하는 컨트롤러입니다.

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

그리고 비동기 호출을 수행하는 라이브러리

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

이 메서드는 '백그라운드'에서 모든 model :: method ()를 처리하기 위해 호출 할 수 있습니다. 가변 인수를 사용합니다.

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

0

제안 : 내부에 9 개의 프레임이 포함 된 FRAMESET HTML 페이지를 포맷하십시오. 각 프레임은 myapp.php 페이지의 다른 "인스턴스"를 가져옵니다. 웹 서버에서 병렬로 실행되는 9 개의 서로 다른 스레드가 있습니다.


0

PHP5.5 +의 경우 mpyw / co 가 최고의 솔루션입니다. 마치 tj / co 인 것처럼 작동합니다.JavaScript에서 .

지정된 여러 GitHub 사용자의 아바타를 다운로드한다고 가정합니다. 각 사용자에 대해 다음 단계가 필요합니다.

  1. http://github.com/mpyw의 콘텐츠 가져 오기 오기 (HTML 가져 오기)
  2. 검색 <img class="avatar" src="...">및 요청 (이미지 가져 오기)

---: 내 응답을 기다리는 중
... 대기 중 : 병렬 흐름에서 다른 응답 대기

많은 유명한 curl_multi기반 스크립트가 이미 다음 흐름을 제공합니다.

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

그러나 이것은 충분히 효율적이지 않습니다. 쓸모없는 대기 시간을 줄이고 싶 ...습니까?

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

예, mpyw / co를 사용하면 매우 쉽습니다. 자세한 내용은 저장소 페이지를 방문하십시오.


-1

페이지의 특정 URL에 POST를 수행 할 때 내 자신의 PHP 기능이 있습니다 ....

샘플 : * 내 함수 사용 ...

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

이 코드를 사용해보십시오 ....

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

CURL php 확장을 활성화하는 것을 잊지 마십시오.


더 빠른 실행을 위해 CURLOPT_TIMEOUT_MS100 밀리 CURLOPT_TIMEOUT초 대신 초 단위로 최소 1 초를 설정할 수 있습니다 .
Jason Silver

-5

이것은 나를 위해 잘 작동합니다. 슬프게도 요청에서 응답을 검색 할 수 없습니다.

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

매우 빠르게 작동하며 원시 tcp 소켓이 필요하지 않습니다. :)


이 함수는 응답에 헤더를 추가합니다. 헤더 요청을 보내지 않습니다. php.net/manual/bg/function.header.php
Lachezar 토도로프
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.