Есть ли способ PHP для создания асинхронных HTTP-вызовов? Меня не волнует ответ, я просто хочу сделать что-то вроде file_get_contents()
, но не дождаться завершения запроса до выполнения остальной части моего кода. Это было бы очень полезно для установки «событий» сорта в моем приложении или запуска длинных процессов.
Есть идеи?
Ответ, который я ранее принял, не сработал. Он все еще ждал ответов. Это работает, хотя, взято из того, как сделать асинхронный запрос GET в PHP?
function post_without_wait($url, $params) { foreach ($params as $key => &$val) { if (is_array($val)) $val = implode(',', $val); $post_params[] = $key.'='.urlencode($val); } $post_string = implode('&', $post_params); $parts=parse_url($url); $fp = fsockopen($parts['host'], isset($parts['port'])?$parts['port']:80, $errno, $errstr, 30); $out = "POST ".$parts['path']." HTTP/1.1\r\n"; $out.= "Host: ".$parts['host']."\r\n"; $out.= "Content-Type: application/x-www-form-urlencoded\r\n"; $out.= "Content-Length: ".strlen($post_string)."\r\n"; $out.= "Connection: Close\r\n\r\n"; if (isset($post_string)) $out.= $post_string; fwrite($fp, $out); fclose($fp); }
это требует php5, я украл его из docs.php.net и отредактировал конец.
Я использую его для мониторинга при возникновении ошибки на сайте клиентов, он отправляет данные мне, не поднимая вывод
function do_post_request($url, $data, $optional_headers = null,$getresponse = false) { $params = array( 'http' => array( 'method' => 'POST', 'content' => $data ) ); if ($optional_headers !== null) { $params['http']['header'] = $optional_headers; } $ctx = stream_context_create($params); $fp = @fopen($url, 'rb', false, $ctx); if (!$fp) { return false; } if ($getresponse) { $response = stream_get_contents($fp); return $response; } return true; }
Если вы контролируете цель, которую хотите вызывать асинхронно (например, собственный «longtask.php»), вы можете закрыть соединение с этого конца, и оба сценария будут выполняться параллельно. Он работает следующим образом:
Я пробовал это, и все работает отлично. Но quick.php ничего не знает о том, как работает longtask.php, если вы не создадите какие-либо средства связи между процессами.
Попробуйте этот код в longtask.php, прежде чем делать что-нибудь еще. Он закроет соединение, но все равно продолжит работу (и подавит любой выход):
while(ob_get_level()) ob_end_clean(); header('Connection: close'); ignore_user_abort(); ob_start(); echo('Connection Closed'); $size = ob_get_length(); header("Content-Length: $size"); ob_end_flush(); flush();
Код скопирован из примечаний пользователя, внесенных в учебник PHP, и несколько улучшился.
Wez Furlong продемонстрировал, как это сделать:
http://netevil.org/blog/2005/may/guru-multiplexing
он предоставил как PHP4-, так и PHP5-совместимые реализации.
Вы можете сделать обман, используя exec () для вызова того, что может выполнять HTTP-запросы, например wget
, но вы должны направлять весь вывод из программы куда-нибудь, например файл или / dev / null, иначе процесс PHP будет ждать этого вывод.
Если вы хотите полностью отделить процесс от потока apache, попробуйте что-то вроде (я не уверен в этом, но надеюсь, что вы поняли эту идею):
exec('bash -c "wget -O (url goes here) > /dev/null 2>&1 &"');
Это не приятный бизнес, и вы, вероятно, захотите что-то вроде задания cron, вызывающего скрипт heartbeat, который опросает реальную очередь событий базы данных для выполнения реальных асинхронных событий.
/** * Asynchronously execute/include a PHP file. Does not record the output of the file anywhere. * * @param string $filename file to execute, relative to calling script * @param string $options (optional) arguments to pass to file via the command line */ function asyncInclude($filename, $options = '') { exec("/path/to/php -f {$filename} {$options} >> /dev/null &"); }
Поддельный аборт запроса с использованием CURL
устанавливающий низкий CURLOPT_TIMEOUT_MS
set ignore_user_abort(true)
чтобы продолжить обработку после закрытия соединения.
С помощью этого метода нет необходимости реализовывать обработку соединений через заголовки и буфер, слишком зависимые от ОС, браузера и версии PHP
Мастер-процесс
function async_curl($background_process=''){ //-------------get curl contents---------------- $ch = curl_init($background_process); curl_setopt_array($ch, array( CURLOPT_HEADER => 0, CURLOPT_RETURNTRANSFER =>true, CURLOPT_NOSIGNAL => 1, //to timeout immediately if the value is < 1000 ms CURLOPT_TIMEOUT_MS => 50, //The maximum number of mseconds to allow cURL functions to execute CURLOPT_VERBOSE => 1, CURLOPT_HEADER => 1 )); $out = curl_exec($ch); //-------------parse curl contents---------------- //$header_size = curl_getinfo($ch, CURLINFO_HEADER_SIZE); //$header = substr($out, 0, $header_size); //$body = substr($out, $header_size); curl_close($ch); return true; } async_curl('http://example.com/background_process_1.php');
Фоновый процесс
ignore_user_abort(true); //do something...
NB
Если вы хотите, чтобы cURL был тайм-аут менее чем за одну секунду, вы можете использовать CURLOPT_TIMEOUT_MS, хотя в «Unix-подобных системах» есть ошибка / «функция», что приводит к немедленному отключению libcurl, если значение <1000 мс с ошибкой " cURL Ошибка (28): время ожидания достигнуто ». Объяснение этого поведения:
[…]
Решение состоит в отключении сигналов с использованием CURLOPT_NOSIGNAL
Ресурсы
время ожидания завивки менее 1000 мс всегда терпит неудачу?
http://www.php.net/manual/en/function.curl-setopt.php#104597
позвольте мне показать вам мой путь 🙂
Требуется узел 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); }
-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); }
-во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); }
Вы можете использовать неблокирующие сокеты и один из расширений pecl для PHP:
Вы можете использовать библиотеку, которая дает вам уровень абстракции между вашим кодом и расширением pecl: https://github.com/reactphp/event-loop
Вы также можете использовать асинхронный http-клиент на основе предыдущей библиотеки: https://github.com/reactphp/http-client
См. Другие библиотеки ReactPHP: http://reactphp.org
Будьте осторожны с асинхронной моделью. Я рекомендую посмотреть это видео на YouTube: http://www.youtube.com/watch?v=MWNcItWuKpI
class async_file_get_contents extends Thread{ public $ret; public $url; public $finished; public function __construct($url) { $this->finished=false; $this->url=$url; } public function run() { $this->ret=file_get_contents($this->url); $this->finished=true; } } $afgc=new async_file_get_contents("http://example.org/file.ext");
Вы можете использовать эту библиотеку: https://github.com/stil/curl-easy
Тогда это довольно просто:
<?php $request = new cURL\Request('http://yahoo.com/'); $request->getOptions()->set(CURLOPT_RETURNTRANSFER, true); // Specify function to be called when your request is complete $request->addListener('complete', function (cURL\Event $event) { $response = $event->response; $httpCode = $response->getInfo(CURLINFO_HTTP_CODE); $html = $response->getContent(); echo "\nDone.\n"; }); // Loop below will run as long as request is processed $timeStart = microtime(true); while ($request->socketPerform()) { printf("Running time: %dms \r", (microtime(true) - $timeStart)*1000); // Here you can do anything else, while your request is in progress }
Ниже вы можете увидеть консольный вывод вышеприведенного примера. Он отобразит простые живые часы, указывающие, сколько времени выполняется:
Расширение swoole. https://github.com/matyhtf/swoole Асинхронная и параллельная сетевая среда для PHP.
$client = new swoole_client(SWOOLE_SOCK_TCP, SWOOLE_SOCK_ASYNC); $client->on("connect", function($cli) { $cli->send("hello world\n"); }); $client->on("receive", function($cli, $data){ echo "Receive: $data\n"; }); $client->on("error", function($cli){ echo "connect fail\n"; }); $client->on("close", function($cli){ echo "close\n"; }); $client->connect('127.0.0.1', 9501, 0.5);
Расширение события очень подходит. Это библиотека библиотеки Libevent , предназначенная для ввода-вывода с событиями, в основном для сетей.
Я написал пример HTTP-клиента, который позволяет планировать несколько HTTP-запросов и запускать их асинхронно.
Это пример клиентского класса HTTP, основанный на расширении Event .
Класс позволяет планировать несколько HTTP-запросов, а затем запускать их асинхронно.
<?php class MyHttpClient { /// @var EventBase protected $base; /// @var array Instances of EventHttpConnection protected $connections = []; public function __construct() { $this->base = new EventBase(); } /** * Dispatches all pending requests (events) * * @return void */ public function run() { $this->base->dispatch(); } public function __destruct() { // Destroy connection objects explicitly, don't wait for GC. // Otherwise, EventBase may be free'd earlier. $this->connections = null; } /** * @brief Adds a pending HTTP request * * @param string $address Hostname, or IP * @param int $port Port number * @param array $headers Extra HTTP headers * @param int $cmd A EventHttpRequest::CMD_* constant * @param string $resource HTTP request resource, eg '/page?a=b&c=d' * * @return EventHttpRequest|false */ public function addRequest($address, $port, array $headers, $cmd = EventHttpRequest::CMD_GET, $resource = '/') { $conn = new EventHttpConnection($this->base, null, $address, $port); $conn->setTimeout(5); $req = new EventHttpRequest([$this, '_requestHandler'], $this->base); foreach ($headers as $k => $v) { $req->addHeader($k, $v, EventHttpRequest::OUTPUT_HEADER); } $req->addHeader('Host', $address, EventHttpRequest::OUTPUT_HEADER); $req->addHeader('Connection', 'close', EventHttpRequest::OUTPUT_HEADER); if ($conn->makeRequest($req, $cmd, $resource)) { $this->connections []= $conn; return $req; } return false; } /** * @brief Handles an HTTP request * * @param EventHttpRequest $req * @param mixed $unused * * @return void */ public function _requestHandler($req, $unused) { if (is_null($req)) { echo "Timed out\n"; } else { $response_code = $req->getResponseCode(); if ($response_code == 0) { echo "Connection refused\n"; } elseif ($response_code != 200) { echo "Unexpected response: $response_code\n"; } else { echo "Success: $response_code\n"; $buf = $req->getInputBuffer(); echo "Body:\n"; while ($s = $buf->readLine(EventBuffer::EOL_ANY)) { echo $s, PHP_EOL; } } } } } $address = "my-host.local"; $port = 80; $headers = [ 'User-Agent' => 'My-User-Agent/1.0', ]; $client = new MyHttpClient(); // Add pending requests for ($i = 0; $i < 10; $i++) { $client->addRequest($address, $port, $headers, EventHttpRequest::CMD_GET, '/test.php?a=' . $i); } // Dispatch pending requests $client->run();
Это пример скрипта на стороне сервера.
<?php echo 'GET: ', var_export($_GET, true), PHP_EOL; echo 'User-Agent: ', $_SERVER['HTTP_USER_AGENT'] ?? '(none)', PHP_EOL;
php http-client.php
Образец вывода
Success: 200 Body: GET: array ( 'a' => '1', ) User-Agent: My-User-Agent/1.0 Success: 200 Body: GET: array ( 'a' => '0', ) User-Agent: My-User-Agent/1.0 Success: 200 Body: GET: array ( 'a' => '3', ) ...
(Стрижка.)
Обратите внимание, что код предназначен для долгосрочной обработки в CLI SAPI .
Для пользовательских протоколов рассмотрите использование низкоуровневого API, то есть событий буфера , буферов . Для сообщений SSL / TLS я бы рекомендовал API низкого уровня в сочетании с контекстом ssl Event. Примеры:
Хотя HTTP-API Libevent прост, он не так гибкий, как буферные события. Например, HTTP API в настоящее время не поддерживает настраиваемые методы HTTP. Но можно реализовать практически любой протокол с использованием низкоуровневого API.
Я также написал образец другого HTTP-клиента, использующего расширение Ev с сокетами в неблокирующем режиме . Код несколько более подробный, чем образец, основанный на событии, потому что Ev – это цикл событий общего назначения. Он не предоставляет сетевые функции, но его наблюдатель EvIo
способен прослушивать файловый дескриптор, инкапсулированный в ресурс сокета, в частности.
Это пример HTTP-клиента на основе расширения Ev .
Расширение Ev реализует простой, но мощный цикл событий общего назначения. Он не обеспечивает сетевых наблюдателей, но его наблюдатель I / O может использоваться для асинхронной обработки сокетов .
Следующий код показывает, как HTTP-запросы могут быть запланированы для параллельной обработки.
<?php class MyHttpRequest { /// @var MyHttpClient private $http_client; /// @var string private $address; /// @var string HTTP resource such as /page?get=param private $resource; /// @var string HTTP method such as GET, POST etc. private $method; /// @var int private $service_port; /// @var resource Socket private $socket; /// @var double Connection timeout in seconds. private $timeout = 10.; /// @var int Chunk size in bytes for socket_recv() private $chunk_size = 20; /// @var EvTimer private $timeout_watcher; /// @var EvIo private $write_watcher; /// @var EvIo private $read_watcher; /// @var EvTimer private $conn_watcher; /// @var string buffer for incoming data private $buffer; /// @var array errors reported by sockets extension in non-blocking mode. private static $e_nonblocking = [ 11, // EAGAIN or EWOULDBLOCK 115, // EINPROGRESS ]; /** * @param MyHttpClient $client * @param string $host Hostname, eg google.co.uk * @param string $resource HTTP resource, eg /page?a=b&c=d * @param string $method HTTP method: GET, HEAD, POST, PUT etc. * @throws RuntimeException */ public function __construct(MyHttpClient $client, $host, $resource, $method) { $this->http_client = $client; $this->host = $host; $this->resource = $resource; $this->method = $method; // Get the port for the WWW service $this->service_port = getservbyname('www', 'tcp'); // Get the IP address for the target host $this->address = gethostbyname($this->host); // Create a TCP/IP socket $this->socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP); if (!$this->socket) { throw new RuntimeException("socket_create() failed: reason: " . socket_strerror(socket_last_error())); } // Set O_NONBLOCK flag socket_set_nonblock($this->socket); $this->conn_watcher = $this->http_client->getLoop() ->timer(0, 0., [$this, 'connect']); } public function __destruct() { $this->close(); } private function freeWatcher(&$w) { if ($w) { $w->stop(); $w = null; } } /** * Deallocates all resources of the request */ private function close() { if ($this->socket) { socket_close($this->socket); $this->socket = null; } $this->freeWatcher($this->timeout_watcher); $this->freeWatcher($this->read_watcher); $this->freeWatcher($this->write_watcher); $this->freeWatcher($this->conn_watcher); } /** * Initializes a connection on socket * @return bool */ public function connect() { $loop = $this->http_client->getLoop(); $this->timeout_watcher = $loop->timer($this->timeout, 0., [$this, '_onTimeout']); $this->write_watcher = $loop->io($this->socket, Ev::WRITE, [$this, '_onWritable']); return socket_connect($this->socket, $this->address, $this->service_port); } /** * Callback for timeout (EvTimer) watcher */ public function _onTimeout(EvTimer $w) { $w->stop(); $this->close(); } /** * Callback which is called when the socket becomes wriable */ public function _onWritable(EvIo $w) { $this->timeout_watcher->stop(); $w->stop(); $in = implode("\r\n", [ "{$this->method} {$this->resource} HTTP/1.1", "Host: {$this->host}", 'Connection: Close', ]) . "\r\n\r\n"; if (!socket_write($this->socket, $in, strlen($in))) { trigger_error("Failed writing $in to socket", E_USER_ERROR); return; } $loop = $this->http_client->getLoop(); $this->read_watcher = $loop->io($this->socket, Ev::READ, [$this, '_onReadable']); // Continue running the loop $loop->run(); } /** * Callback which is called when the socket becomes readable */ public function _onReadable(EvIo $w) { // recv() 20 bytes in non-blocking mode $ret = socket_recv($this->socket, $out, 20, MSG_DONTWAIT); if ($ret) { // Still have data to read. Append the read chunk to the buffer. $this->buffer .= $out; } elseif ($ret === 0) { // All is read printf("\n<<<<\n%s\n>>>>", rtrim($this->buffer)); fflush(STDOUT); $w->stop(); $this->close(); return; } // Caught EINPROGRESS, EAGAIN, or EWOULDBLOCK if (in_array(socket_last_error(), static::$e_nonblocking)) { return; } $w->stop(); $this->close(); } } ///////////////////////////////////// class MyHttpClient { /// @var array Instances of MyHttpRequest private $requests = []; /// @var EvLoop private $loop; public function __construct() { // Each HTTP client runs its own event loop $this->loop = new EvLoop(); } public function __destruct() { $this->loop->stop(); } /** * @return EvLoop */ public function getLoop() { return $this->loop; } /** * Adds a pending request */ public function addRequest(MyHttpRequest $r) { $this->requests []= $r; } /** * Dispatches all pending requests */ public function run() { $this->loop->run(); } } ///////////////////////////////////// // Usage $client = new MyHttpClient(); foreach (range(1, 10) as $i) { $client->addRequest(new MyHttpRequest($client, 'my-host.local', '/test.php?a=' . $i, 'GET')); } $client->run();
Предположим, скрипт http://my-host.local/test.php
печатает дамп $_GET
:
<?php echo 'GET: ', var_export($_GET, true), PHP_EOL;
Затем вывод команды php http-client.php
будет похож на следующий:
<<<< HTTP/1.1 200 OK Server: nginx/1.10.1 Date: Fri, 02 Dec 2016 12:39:54 GMT Content-Type: text/html; charset=UTF-8 Transfer-Encoding: chunked Connection: close X-Powered-By: PHP/7.0.13-pl0-gentoo 1d GET: array ( 'a' => '3', ) 0 >>>> <<<< HTTP/1.1 200 OK Server: nginx/1.10.1 Date: Fri, 02 Dec 2016 12:39:54 GMT Content-Type: text/html; charset=UTF-8 Transfer-Encoding: chunked Connection: close X-Powered-By: PHP/7.0.13-pl0-gentoo 1d GET: array ( 'a' => '2', ) 0 >>>> ...
(обрезается)
Обратите внимание, что в PHP 5 расширение сокетов может записывать предупреждения для значений errno
EINPROGRESS
, EAGAIN
и EWOULDBLOCK
. Можно отключить журналы с помощью
error_reporting(E_ERROR);
Я просто хочу сделать что-то вроде
file_get_contents()
, но не дождался завершения запроса до выполнения остальной части моего кода.
Код, который должен выполняться параллельно с сетевыми запросами, может выполняться, например, при обратном вызове таймера события или, например, для наблюдателя бездействия Ev. Вы можете легко понять это, просмотрев образцы, упомянутые выше. В противном случае я добавлю еще один пример 🙂
Вот рабочий пример, просто запустите его и откройте storage.txt после этого, чтобы проверить магический результат
<?php function curlGet($target){ $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $target); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); $result = curl_exec ($ch); curl_close ($ch); return $result; } // Its the next 3 lines that do the magic ignore_user_abort(true); header("Connection: close"); header("Content-Length: 0"); echo str_repeat("s", 100000); flush(); $i = $_GET['i']; if(!is_numeric($i)) $i = 1; if($i > 4) exit; if($i == 1) file_put_contents('storage.txt', ''); file_put_contents('storage.txt', file_get_contents('storage.txt') . time() . "\n"); sleep(5); curlGet($_SERVER['HTTP_HOST'] . $_SERVER['SCRIPT_NAME'] . '?i=' . ($i + 1)); curlGet($_SERVER['HTTP_HOST'] . $_SERVER['SCRIPT_NAME'] . '?i=' . ($i + 1));
Вот моя собственная функция PHP, когда я делаю POST на определенный URL любой страницы …. Пример: *** использование моей функции …
<?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>
по<?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>
Ну, тайм-аут можно установить в миллисекундах, см. «CURLOPT_CONNECTTIMEOUT_MS» в http://www.php.net/manual/en/function.curl-setopt