Several thoughts on php multithreading

Source: Internet
Author: User
Tags fread php multithreading strlen

Is there a way to implement multithreading in PHP? Suppose you are writing a PHP application based on multiple servers. Ideally, you can send requests to multiple servers at the same time, instead of one server after another. Can it be implemented? 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: Copy code
$ 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.0 rnHost: $ 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:

The code is as follows: Copy code
$ 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.0 rnHost :"
. $ 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 an 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 already compiled PHP with sockets (ext/sockets) support, you can use the same code on 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: Copy code

Define ('einss SS', 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.

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.