Recently, Lao Tie opened a live broadcast. Welcome to join us!

  • PHP advanced road – 100 million level PV website architecture technical details and routines

  • PHP advanced road – 100 million pv site architecture actual performance squeeze

  • The path to PHP advancement – A quick entry into Java development for backend diversification

The server implemented in this article is only for demonstration and understanding principle, and strive to be easy to understand. Interested friends can continue to further transformation

If you have a Real Web server, you need to have a general understanding of how web servers work. Start with a static text server, using 1.html on a Web server as an example

1. The client by sending an HTTP request to the server, if the server is listening port number is 9002, then in the machine itself test access address is http://localhost:9002/1.html.

2. The server listens to port 9002. After receiving the request, the server can obtain the location of the URI resource in the Web directory from the HTTP head header.

3. The server reads the resource file to be accessed, fills the file into the HTTP entity and returns the file to the client.

The schematic diagram is as follows:




       
class web_config {
    // The port number to listen to
    const PORT = 9003;
    // Project root directory
    const WEB_ROOT = "/Users/zhoumengkang/Documents/html";
}


class server {
    private $ip;
    private $port;
    public function __construct($ip, $port) {
        $this->ip = $ip;
        $this->port = $port;
        $this->await();
    }
    private function await(a) {
        $sock = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
        if ($sock < 0) {
            echo "Error:" . socket_strerror(socket_last_error()) . "\n";
        }
        $ret = socket_bind($sock, $this->ip, $this->port);
        if(! $ret) {echo "BIND FAILED:" . socket_strerror(socket_last_error()) . "\n";
            exit;
        }
        echo "OK\n";
        $ret = socket_listen($sock);
        if ($ret < 0) {
            echo "LISTEN FAILED:" . socket_strerror(socket_last_error()) . "\n";
        }
        do {
            $new_sock = null;
            try {
                $new_sock = socket_accept($sock);
            } catch (Exception $e) {
                echo $e->getMessage();
                echo "ACCEPT FAILED:" . socket_strerror(socket_last_error()) . "\n";
            }
            try {
                $request_string = socket_read($new_sock, 1024);
                $response = $this->output($request_string);
                socket_write($new_sock, $response);
                socket_close($new_sock);
            } catch (Exception $e) {
                echo $e->getMessage();
                echo "READ FAILED:" . socket_strerror(socket_last_error()) . "\n"; }}while (TRUE);
    }
    / * * *@param $request_string
     * @return string
     */
    private function output($request_string){
        // static GET /1.html HTTP/1.1...
        $request_array = explode("",$request_string);
        if(count($request_array) < 2) {return $this->not_found();
        }
        $uri = $request_array[1];
        $filename = web_config::WEB_ROOT . $uri;
        echo "request:".$filename."\n";
        // Static file processing
        if (file_exists($filename)) {
            return $this->add_header(file_get_contents($filename));
        } else {
            return $this->not_found(); }}/** * 404 returns *@return string
     */
    private function not_found(a){
        $content = "<h1>File Not Found </h1>";
        return "HTTP/1.1 404 File Not Found\r\ ncontent-type: text/ HTML \r\nContent-Length:".strlen($content)."\r\n\r\n".$content;
    }
    /** * + header *@param $string
     * @return string
     */
    private function add_header($string){
        return "HTTP / 1.1 OK \ r \ nContent - Length: 200".strlen($string)."\r\nServer: mengkang\r\n\r\n".$string;
    }
}
$server = new server("127.0.0.1", web_config::PORT);Copy the code

The code has been uploaded to github github.com/zhoumengka….

As shown in the code above, simply execute the file at the terminal and a static Web server starts.

Below is a screenshot of me accessing the 1.jpg file in my Web directory

Now that a simple static Web server is complete, the question is how to make it support the output of dynamic content. Do you simply execute a program inside the Web server and return the results to the client? But the code of the Web server and the business code are coupled together, how to solve a Web server, can be used in various business scenarios?

The advent of CGI solves this problem. So what is CGI? The following was copied:

CGI is an interface standard between external applications (CGI programs) and Web servers, and a discipline for passing information between CGI programs and Web servers. The CGI specification allows Web servers to execute external programs and send their output to Web browsers. CGI turns a simple set of static hypermedia documents on the Web into a complete new interactive medium.

For example, the PHP global variable $_SERVER[‘QUERY_STRING’] that we’re using is passed by the Web server via CGI. In Nginx, for example, you may remember this fastCGI configuration



fastcgi_param  QUERY_STRING       $query_string;Copy the code

Yes, nginx passes its global variable $query_string to the fastcgi_param environment variable.

Below we also use the CGI QUERY_STRING as a bridge to pass information from the uri requested by the client to the CGI program. Put QUERY_STRING into the request’s environment variable via putenv.

The convention is that the resources accessed in the Web server are.cgi and the suffix means dynamic access, a bit like nginx configuring location to find PHP scripts. Are rules to check whether a CGI program should be requested. To distinguish myself from the Web server, I wrote a CGI program in C that queries user information based on user ID.

The general access logic is shown in the following figure

Demo code address: github.com/zhoumengka….

To run demo, perform the following operations

1. Change the project root directory WEB_ROOT in config. PHP

2. Compile cgi-demo user.c, run GCC -o user.cgi user.c, and place the user.cgi file under the root directory of your configured project

3. Run PHP start. PHP on the terminal to start the Web server

4. Through http://localhost:9003/user.cg… You can access it and see the following

In fact, just on the basis of the static server to do some CGI judgment is the request of forwarding processing, the github three files of the code into a file for everyone to see




       
class web_config {

    // The port number to listen to
    const PORT = 9003;

    // Project root directory
    const WEB_ROOT = "/Users/zhoumengkang/Documents/html";

    // The file extension of the system supported CGI program
    const CGI_EXTENSION = "cgi";

}

class server {
    private $ip;
    private $port;
    public function __construct($ip, $port) {
        $this->ip = $ip;
        $this->port = $port;
        $this->await();
    }
 
    private function await(a) {
        $sock = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
        if ($sock < 0) {
            echo "Error:" . socket_strerror(socket_last_error()) . "\n";
        }
 
        $ret = socket_bind($sock, $this->ip, $this->port);
        if(! $ret) {echo "BIND FAILED:" . socket_strerror(socket_last_error()) . "\n";
            exit;
        }
        echo "OK\n";
 
        $ret = socket_listen($sock);
        if ($ret < 0) {
            echo "LISTEN FAILED:" . socket_strerror(socket_last_error()) . "\n";
        }
 
        do {
            $new_sock = null;
            try {
                $new_sock = socket_accept($sock);
            } catch (Exception $e) {
                echo $e->getMessage();
                echo "ACCEPT FAILED:" . socket_strerror(socket_last_error()) . "\n";
            }
            try {
                $request_string = socket_read($new_sock, 1024);
                $response = $this->output($request_string);
                socket_write($new_sock, $response);
                socket_close($new_sock);
            } catch (Exception $e) {
                echo $e->getMessage();
                echo "READ FAILED:" . socket_strerror(socket_last_error()) . "\n"; }}while (TRUE);
    }
    / * * *@param $request_string
     * @return string
     */
    private function output($request_string){
        // static GET /1.html HTTP/1.1...
        // dynamic GET /user.cgi? Id = 1 HTTP / 1.1...
        $request_array = explode("",$request_string);
        if(count($request_array) < 2) {return "";
        }
        $uri = $request_array[1];
        echo "request:".web_config::WEB_ROOT . $uri."\n";
        $query_string = null;
        if ($uri == "/favicon.ico") {
            return "";
        }
        if (strpos($uri,"?")) {
            $uriArr = explode("?", $uri);
            $uri = $uriArr[0];
            $query_string = isset($uriArr[1])? $uriArr[1] : null;
        }
        $filename = web_config::WEB_ROOT . $uri;
        if ($this->cgi_check($uri)) {
            
            $this->set_env($query_string);
            $handle = popen(web_config::WEB_ROOT.$uri, "r");
            $read = stream_get_contents($handle);
            pclose($handle);
            return $this->add_header($read);
        }
        // Static file processing
        if (file_exists($filename)) {
            return $this->add_header(file_get_contents($filename));
        } else {
            return $this->not_found(); }}/** * Sets environment variables for cgi programs to use *@param $query_string
     * @return bool
     */
    private function set_env($query_string){
        if($query_string == null) {return false;
        }
        if (strpos($query_string, "=")) {
            putenv("QUERY_STRING=".$query_string); }}/** * Determine if the requested URI is a valid CGI resource *@param $uri
     * @return bool
     */
    private function cgi_check($uri){
        $info = pathinfo($uri);
        $extension = isset($info["extension"])? $info["extension"] : null;
        if( $extension && in_array($extension,explode(",",web_config::CGI_EXTENSION))){
            return true;
        }
        return false;
    }
    /** * 404 returns *@return string
     */
    private function not_found(a){
        $content = "<h1>File Not Found </h1>";
        return "HTTP/1.1 404 File Not Found\r\ ncontent-type: text/ HTML \r\nContent-Length:".strlen($content)."\r\n\r\n".$content;
    }
    /** * + header *@param $string
     * @return string
     */
    private function add_header($string){
        return "HTTP / 1.1 OK \ r \ nContent - Length: 200".strlen($string)."\r\nServer: mengkang\r\n\r\n".$string;
    }
}

$server = new server("127.0.0.1", web_config::PORT);Copy the code

Recently, Lao Tie opened a live broadcast. Welcome to join us!

  • PHP advanced road – 100 million level PV website architecture technical details and routines

  • The path to PHP advancement – A quick entry into Java development for backend diversification