Reply:
When someone wants to implement concurrency, they often think of using fork or spawn
threads, but when they find that PHP does not support multithreading, it is likely to switch ideas to use some of the language that is not good enough, such as Perl.
In fact, in most cases, you don't have to use fork or thread, and you get better performance than fork or thread.
Suppose you want to set up a service to check the running N servers to make sure they're still working. You might write the following code:
copy code code is as follows:
!--? PHP $ hosts = Array ("host1.sample.com", "host2.sample.com", "host3.sample.com");
$timeout = n; $status = array ();
foreach ($hosts as $host) {
$errno = 0;
$errstr = "";
$s = fsockopen ($host, $errno, $errstr, $timeout);
if ($s) {
$status [$host] = "Connectedn";
Fwrite ($s, "head/http/1.0rnhost: $hostrnrn");
Do {
$data = fread ($s, 8192);
if (strlen ($data) = = 0) {break;}
$status [$host]. = $data;
} while (true); Fclose ($s);
} else {
$status [$host] = "Connection failed: $errno $errstrn";
}
}
Print_r ($status);
?
It works fine, but before Fsockopen () analyzes hostname and establishes a successful connection (or delay $timeout seconds), it takes a long time to expand the code to manage a large number of servers.
So we have to give up this code; We can establish an asynchronous connection-there is no need to wait for Fsockopen to return to the connection state. PHP still needs to parse hostname (so it's more sensible to use IP directly), but will return immediately after opening a connection, and then we can connect to the next server.
There are two ways to do this, and you can replace Fsocketopen () directly with the new Stream_socket_client () function in PHP5. PHP5 the previous version, you need to do it yourself and use the sockets extension to solve the problem.
Here are the workarounds in PHP5:
Copy CodeThe code is as follows:
$hosts = Array ("host1.sample.com", "host2.sample.com", "host3.sample.com");
$timeout = 15;
$status = Array ();
$sockets = Array ();
foreach ($hosts as $id = = $host) {
$s = Stream_socket_client ("$host:", $errno, $errstr, $timeout, stream_client_async_connect| Stream_client_connect);
if ($s) {
$sockets [$id] = $s;
$status [$id] = "in progress";
} else {
$status [$id] = "failed, $errno $errstr";
}
}
while (count ($sockets)) {
$read = $write = $sockets;
$n = Stream_select ($read, $write, $e = null, $timeout);
if ($n > 0) {
foreach ($read as $r) {
$id = Array_search ($r, $sockets);
$data = Fread ($r, 8192);
if (strlen ($data) = = 0) {
if ($status [$id] = = "in progress") {
$status [$id] = "failed to connect";
}
Fclose ($R);
Unset ($sockets [$id]);
} else {
$status [$id]. = $data;
}
}
foreach ($write as $w) {
$id = Array_search ($w, $sockets);
Fwrite ($w, "Head/http/1.0rnhost:".) $hosts [$id]. "Rnrn");
$status [$id] = "Waiting for response";
}
} else {
foreach ($sockets as $id = = $s) {
$status [$id] = "Timed out". $status [$id];
}
Break
}
}
foreach ($hosts as $id = = $host) {
echo "Host: $hostn"; echo "Status:". $status [$id]. "NN";
}
?>
We use Stream_select () to wait for sockets to open the connection event. Stream_select () calls the system's Select (2) function to work: The first three parameters are the array of streams you want to use, and you can read, write, and get exceptions (for three parameters, respectively). Stream_select () Can wait for an event to occur by setting the $timeout (seconds) parameter-the corresponding sockets data will be written to the parameter you passed in when the event occurs.
The following is the implementation of the version after PHP4.1.0, if you have compiled PHP with sockets (ext/sockets) support, you can use the root above similar code, just need to use the Streams/filesystem function above the function of ext/ The sockets function is implemented. The main difference is that we use the following function instead
Stream_socket_client () To establish the connection:
copy code code as follows:
!--? PHP // This value was correct for Linux, and other systems had other values
define (' einprogress ', 115);
Function Non_blocking_connect ($host, $port, & $errno, & $errstr, $timeout) {
$ip = gethostbyname ($host); br> $s = socket_create (af_inet, sock_stream, 0);
if (Socket_set_nonblock ($s)) {
$r = @socket_connect ($s, $ip, $port);
if ($r | | socket_last_error () = = einprogress) {
$errno = einprogress; return $s;
}
}
$errno = Socket_last_error ($s);
$errstr = Socket_strerror ($errno);
Socket_close ($s);
return false;
}
?
Now replace Stream_select () with Socket_select (), replace fread () with Socket_read (),
Socket_write () Replace fwrite () and replace fclose () with Socket_close () to execute the script!
PHP5 's advanced is that you can handle almost any stream-with Stream_select () For example, you can use the Include
STDIN uses it to receive keyboard input and save it into an array, and you can also receive data from a pipeline opened by Proc_open ().
If you want php4.3.x to have the ability to handle streams, I've prepared a patch for you that Fsockopen can work asynchronously. Do not agree with the patch, the patch will not appear in the official version of PHP, I included in the patch stream_socket_client () function implementation, through which you can make your script compatible
PHP5.
http://www.bkjia.com/PHPjc/718626.html www.bkjia.com true http://www.bkjia.com/PHPjc/718626.html techarticle answer: When someone wants to implement concurrency, they usually think of using fork or spawn threads, but when they find that PHP does not support multithreading, it will probably change the idea to use a ...