Two implementation methods of multithreading in PHP and two implementation methods of multithreading in php

Source: Internet
Author: User
Tags php multithreading

Two implementation methods of multithreading in PHP and two implementation methods of multithreading in php

PHP itself does not support multithreading, but we can use other methods to implement multithreading, such as shell services, such as web servers. In this article, we will talk about how to implement these two methods. For more information, see.

Multithreading is a very good thing in java. Many friends say that php multithreading cannot be used in PHP. In fact, it is wrong to say that the implementation method of PHP multithreading is related to the fsockopen function, next we will introduce the specific implementation program code. For more information, see.

When someone wants to implement concurrent functions, they usually think of using fork or spawn threads. But when they find that php does not support multithreading, they will probably change their thinking to use some bad languages, for example, perl.

In fact, in most cases, you do not need to use fork or thread, and you will get better performance than using fork or thread.

Suppose you want to create a service to check the running n servers to make sure they are still running normally. You may write the following code:

The Code is as follows:

<?php$hosts = array("host1.sample.com", "host2.sample.com", "host3.sample.com");$timeout = 15;$status = array();foreach ($hosts as $host) {$errno = 0; $errstr = ""; $s = fsockopen($host, 80, $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 runs well, but it takes a long time to expand the code to manage a large number of servers before fsockopen () analyzes the hostname and establishes a successful connection (or delay $ timeout seconds.

Therefore, we must discard this Code; we can establish an asynchronous connection-no need to wait for fsockopen to return the connection status. PHP still needs to parse the hostname (so it is more wise to directly use the ip address), but it will return immediately after opening a connection, and then we can connect to the next server.

There are two ways to achieve this. In PHP5, you can use the newly added stream_socket_client () function to directly replace fsocketopen (). In versions earlier than PHP5, You Need To Do It Yourself and use the sockets extension to solve the problem.

The solution in PHP5 is as follows:

It runs well, but it takes a long time to expand the code to manage a large number of servers before fsockopen () analyzes the hostname and establishes a successful connection (or delay $ timeout seconds.

Therefore, we must discard this Code; we can establish an asynchronous connection-no need to wait for fsockopen to return the connection status. PHP still needs to parse the hostname (so it is more wise to directly use the ip address), but it will return immediately after opening a connection, and then we can connect to the next server.

There are two ways to achieve this. In PHP5, you can use the newly added stream_socket_client () function to directly replace fsocketopen (). In versions earlier than PHP5, You Need To Do It Yourself and use the sockets extension to solve the problem.

The Code is as follows:

<?php$hosts = array("host1.sample.com", "host2.sample.com", "host3.sample.com");$timeout = 15;$status = array();$sockets = array();/* Initiate connections to all the hosts simultaneously */foreach ($hosts as $id => $host) { $s = stream_socket_client("$$host:80", $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"; }}/* Now, wait for the results to come back in */while (count($sockets)) { $read = $write = $sockets; /* This is the magic function - explained below */ $n = stream_select($read, $write, $e = null, $timeout); if ($n > 0) { /* readable sockets either have data for us, or are failed * connection attempts */ 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;  } } /* writeable sockets can accept an HTTP request */ foreach ($write as $w) { $id = array_search($w, $sockets); fwrite($w, "HEAD / HTTP/1.0rnHost: " . $hosts[$id] . "rnrn"); $status[$id] = "waiting for response"; } } else { /* timed out waiting; assume that all hosts associated * with $sockets are faulty */ 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 the connection event opened by sockets. Stream_select () calls the system's select (2) function to work: the first three parameters are the array of the streams you want to use; you can read them, an error occurred while writing and retrieving data (three parameters respectively ). Stream_select () You can set the $ timeout (second) parameter to wait for the event to happen-when the event occurs, the corresponding sockets data will be written into your input parameters.

The following is the implementation of PHP4.1.0 and later versions. If you have compiled PHP with sockets (ext/sockets) support, you can use the same code as the root, the preceding functions of the streams/filesystem function must be implemented using the ext/sockets function. The main difference is that we use the following function instead of stream_socket_client () to establish a connection:

The Code is as follows:

<?php// This value is correct for Linux, other systems have other valuesdefine('EINPROGRESS', 115);function non_blocking_connect($host, $port, &$errno, &$errstr, $timeout) { $ip = gethostbyname($host); $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;}?> 

Replace stream_select () with socket_select (), replace fread () with socket_read (), replace fwrite () with socket_write (), and replace fclose () with socket_close () you can execute the script!

PHP5 is advanced in that you can use stream_select () to process almost all streams. For example, you can use include STDIN to receive keyboard input and save it to an array, you can also receive data in the pipeline opened through proc_open.

Next we will share a PHP multithreading class.

The Code is as follows:

class thread {  var $hooks = array(); var $args = array();  function thread() { }  function addthread($func) {  $args = array_slice(func_get_args(), 1);  $this->hooks[] = $func;  $this->args[] = $args;  return true; }  function runthread() {  if(isset($_GET['flag']))  {   $flag = intval($_GET['flag']);  }  if($flag || $flag === 0)  {   call_user_func_array($this->hooks[$flag], $this->args[$flag]);  }  else  {   for($i = 0, $size = count($this->hooks); $i < $size; $i++)   {    $fp=fsockopen($_SERVER['HTTP_HOST'],$_SERVER['SERVER_PORT']);    if($fp)    {     $out = "GET {$_SERVER['PHP_SELF']}?flag=$i HTTP/1.1rn";     $out .= "Host: {$_SERVER['HTTP_HOST']}rn";     $out .= "Connection: Closernrn";     fputs($fp,$out);     fclose($fp);    }   }  } }}

Thank you for reading this article. I hope it will help you. Thank you for your support for this site!

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.