This article summarizes approximately five concurrent methods in PHP Programming:
1.curl_multi_init
The document says allows the processing of multiple curl Handles asynchronously. is really asynchronous. What needs to be understood here is the Select method, which is interpreted in the document as blocks until there is, the "any of" curl_multi connections. Understanding the common asynchronous model should be understandable, select, Epoll, are well-known
<?php/build the individual requests as above, but does not execute them $ch _1 = Curl_
Init (' http://www.jb51.net/');
$ch _2 = curl_init (' http://www.jb51.net/');
curl_setopt ($ch _1, Curlopt_returntransfer, true);
curl_setopt ($ch _2, Curlopt_returntransfer, true);
Build the Multi-curl handle, adding both $ch $mh = Curl_multi_init ();
Curl_multi_add_handle ($MH, $ch _1);
Curl_multi_add_handle ($MH, $ch _2);
Execute all queries simultaneously, and continue the all are complete $running = null;
do {curl_multi_exec ($MH, $running);
$ch = Curl_multi_select ($MH);
if ($ch!== 0) {$info = Curl_multi_info_read ($MH);
if ($info) {var_dump ($info);
$response _1 = curl_multi_getcontent ($info [' handle ']);
echo "$response _1 \ n";
Break
}} while ($running > 0);
Close the handles Curl_multi_remove_handle ($MH, $ch _1);
Curl_multi_remove_handle ($MH, $ch _2);
Curl_multi_close ($MH);
What I set here is that when the select gets the result, it exits the loop and deletes the curl resource to cancel the HTTP request.
2.swoole_client
Swoole_client provides asynchronous mode, I forgot this. The sleep method here requires a swoole version greater than or equal to 1.7.21, and I haven't been able to get to this version, so direct exit is OK.
<?php
$client = new Swoole_client (swoole_sock_tcp, swoole_sock_async);
Set the event callback function
$client->on ("Connect", function ($CLI) {
$req = "get/http/1.1\r\n
host:www.jb51.net\r\n
connection:keep-alive\r\n
cache-control:no-cache\r\n
pragma:no-cache\r\n\r\n ";
For ($i =0 $i < 3 $i + +) {
$cli->send ($req);
}
);
$client->on ("Receive", Function ($CLI, $data) {
echo "Received:". $data. " \ n ";
Exit (0);
$cli->sleep (); Swoole >= 1.7.21
});
$client->on ("Error", function ($CLI) {
echo "Connect failed\n";
});
$client->on ("Close", function ($CLI) {
echo "Connection close\n";
});
Initiate network connection
$client->connect (' 183.207.95.145 ', 80, 1);
3.process
Hey, almost forgot the swoole_process, there is no pcntl module. But after writing the discovery, this is not actually a interrupt request, but which one to read first, ignoring the return value after.
<?php $workers = []; $worker _num = 3;//The number of processes created $finished = false; $lock = new swoole_l
Ock (Swoole_mutex);
For ($i =0 $i < $worker _num $i + +) {$process = new swoole_process (' process ');
$process->usequeue ();
$pid = $process->start ();
$workers [$pid] = $process; The foreach ($workers as $pid => $process) {//subprocess will also contain this event Swoole_event_add ($process->pipe, function ($pipe) use ($PR
Ocess, $lock, & $finished) {$lock->lock ();
if (! $finished) {$finished = true;
$data = $process->read (); echo "RECV:". $data.
Php_eol;
} $lock->unlock ();
});
The function process (swoole_process $process) {$response = ' http response ';
$process->write ($response); echo $process->pid, "T", $process->callback.
Php_eol;
for ($i = 0; $i < $worker _num $i + +) {$ret = Swoole_process::wait ();
$pid = $ret [' pid ']; echo "Worker Exit, pid=". $pid.
Php_eol; }
4.pthreads
when compiling the Pthreads module, you are prompted to open the Zts when PHP compiles, so it appears that the thread safe version must be available. Wamp PHP is just the TS, directly under the DLL, the document in the instructions copied to the corresponding directory, the win under the test. Not fully understood, found that the article said PHP pthreads and POSIX pthreads is completely different. Code is a bit rotten, but also need to look at the document, experience.
<?php
class Foo extends stackable {public
$url;
public $response = null;
Public Function __construct () {
$this->url = ' http://www.jb51.net ';
}
Public Function Run () {}
}
class Process extends Worker {
private $text = "";
Public function __construct ($text, $object) {
$this->text = $text;
$this->object = $object;
}
Public Function run () {while
(Is_null ($this->object->response)) {
print Thread {$this->text} is Running\n ";
$this->object->response = ' http response ';
Sleep (1);
}}} $foo = new Foo ();
$a = new Process ("a", $foo);
$a->start ();
$b = new Process ("B", $foo);
$b->start ();
Echo $foo->response;
5.yield
to write asynchronous code synchronously:
<?php class Asyncserver {protected $handler;
protected $socket;
protected $tasks = [];
protected $timers = [];
Public function __construct (callable $handler) {$this->handler = $handler;
$this->socket = socket_create (Af_inet, Sock_dgram, SOL_UDP); if (! $this->socket) {die Socket_strerror (Socket_last_error ()). "
\ n "); } if (!socket_set_nonblock ($this->socket)) {die (Socket_last_error ()). "
\ n "); } if (!socket_bind ($this->socket, 0.0.0.0, 1234)) {die (Socket_strerror ()). "
\ n ");
The Public Function Run () {while (true) {$now = Microtime (True) * 1000;
foreach ($this->timers as $time => $sockets) {if ($time > $now) break;
foreach ($sockets as $one) {list ($socket, $coroutine) = $this->tasks[$one];
unset ($this->tasks[$one]);
Socket_close ($socket); $coroutinE->throw (New Exception ("Timeout"));
} unset ($this->timers[$time]);
} $reads = Array ($this->socket);
foreach ($this->tasks as List ($socket)) {$reads [] = $socket;
} $writes = NULL;
$excepts = NULL;
if (!socket_select ($reads, $writes, $excepts, 0, 1000)) {continue;
foreach ($reads as $one) {$len = Socket_recvfrom ($one, $data, 65535, 0, $ip, $port);
if (! $len) {//echo "Socket_recvfrom fail.\n";
Continue } if ($one = = $this->socket) {//echo] [run]request recvfrom succ.
Data= $data ip= $ip port= $port \ n ";
$handler = $this->handler;
$coroutine = $handler ($one, $data, $len, $ip, $port);
if (! $coroutine) {//echo "[run]everything is done.\n";
Continue
$task = $coroutine->current (); echo "[Run]asynctask RecV. data= $task->data ip= $task->ip port=->port $task timeout= $task->timeout\n ";
$socket = Socket_create (Af_inet, Sock_dgram, SOL_UDP); if (! $socket) {//echo socket_strerror (Socket_last_error ()). "
\ n ";
$coroutine->throw (New Exception (Socket_strerror (Socket_last_error ()), Socket_last_error ());
Continue } if (!socket_set_nonblock ($socket)) {//echo socket_strerror (Socket_last_error ()). "
\ n ";
$coroutine->throw (New Exception (Socket_strerror (Socket_last_error ()), Socket_last_error ());
Continue
Socket_sendto ($socket, $task->data, $task->len, 0, $task->ip, $task->port);
$deadline = $now + $task->timeout;
$this->tasks[$socket] = [$socket, $coroutine, $deadline];
$this->timers[$deadline] [$socket] = $socket; else {//echo] [run]response recvfrom succ. Data= $data ip= $ip port= $port \ n ";
List ($socket, $coroutine, $deadline) = $this->tasks[$one];
unset ($this->tasks[$one]);
unset ($this->timers[$deadline] [$one]);
Socket_close ($socket);
$coroutine->send (Array ($data, $len));
Class Asynctask {public $data}}}}
Public $len;
Public $ip;
Public $port;
Public $timeout;
Public function __construct ($data, $len, $ip, $port, $timeout) {$this->data = $data;
$this->len = $len;
$this->ip = $ip;
$this->port = $port;
$this->timeout = $timeout; } function Asyncsendrecv ($req _buf, $req _len, $ip, $port, $timeout) {return new Asynctask ($req _buf, $req _len, $ip
, $port, $timeout); function RequestHandler ($socket, $req _buf, $req _len, $ip, $port) {//echo "[RequestHandler] before yield .
req= $req _buf\n "; try {list ($rsp _buf, $rsp _len) = (yield Asyncsendrecv ($req _buf, $req _len, "127.0.0.1", 2345, 3000));
The catch (Exception $ex) {$rsp _buf = $ex->getmessage ();
$RSP _len = strlen ($rsp _buf);
echo "[Exception] $rsp _buf\n"; //echo "[RequestHandler] after yield asynctask.
rsp= $rsp _buf\n ";
Socket_sendto ($socket, $rsp _buf, $rsp _len, 0, $ip, $port);
} $server = new Asyncserver (RequestHandler);
$server->run ();
?>
Code interpretation:
The use of PHP built-in array capabilities, to achieve a simple "time-out management", in milliseconds as the precision of time slicing;
Encapsulates ASYNCSENDRECV interfaces, calling shapes such as yield asyncsendrecv (), more natural;
Add exception as an error handling mechanism, add ret_code can also be used for display only.