The following is an illustrated way to introduce PHP to implement a dynamic Web server, the details are as follows:
The server implemented in this paper is just a demonstration and understanding of the principles used, and strive to be easy to understand. Interested friends can continue to deepen the transformation
If a Web server is real, then you need to know how the Web server works. Start with a static text server to access the Web server 1.html for example
1. Client sends an HTTP request to the server, if the server listens to the port number is 9002, then the native test access address is http://localhost:9002/1.html .
2. The server listens for 9002 ports, and after receiving a request, it is able to obtain the location of the URI resource in the Web directory that needs to be accessed in the request from the HTTP head header.
3. The server reads the resource file that needs to be accessed, and then populates the HTTP entity to return it to the client.
The schematic diagram is as follows:
PHP <?php class Web_config {//Listener port number 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 () {$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 ";
The processing of static files if (File_exists ($filename)) {return $this->add_header ($filename));
else {return $this->not_found (); }/** * 404 returns * @return String */Private Function Not_found () {$content = "
Code has been uploaded GitHub Https://github.com/zhoumengkang/php/tree/master/php-webserver/static
As mentioned in the code above, as long as the file is executed at the terminal, a static Web server is started.
The following image gives me a screenshot of the 1.jpg files in my web directory
A simple static Web server has been completed, and the following question is how to make it support the output of dynamic content. Is it only necessary to finish a program inside the Web server and return the results to the client? However, the Web server's code is coupled with the business code, how to solve a Web server, can be used in various business scenarios?
The presence of CGI solves the problem. So what is a CGI? The following passage copies:
CGI is the interface standard between an external application (CGI program) and a Web server, and is a procedure for transferring information between a CGI program and a Web server. The CGI specification allows Web servers to execute external programs and send their output to a Web browser, and CGI turns a simple set of static hypermedia documents on the Web into a complete new interactive medium.
Good halo, for example, we are using the global variables of PHP $_SERVER['QUERY_STRING']
is the WEB server through the CGI protocol, passed over. For example in Nginx, perhaps you remember such a fastcgi configuration
Copy Code code as follows:
Fastcgi_param
Query_string
$query _string;
Yes, Nginx has passed its global variable $query_string
to the FASTCGI_PARAM environment variable.
We also use CGI as a QUERY_STRING
bridge to pass information from the URI requested by the client to the CGI program. The putenv
manner in which the QUERY_STRING
request is stored in the environment variable.
Our agreement that the resources accessed in the WEB server are .cgi
suffixes means dynamic access, which is somewhat similar to the Nginx configuration location to look for PHP scripts. is a rule that checks whether a CGI program should be requested. To differentiate it from the WEB server, I wrote a CGI program that queried user information in C, and queried user information based on the user ID.
The approximate access logic is shown below
Demo Code Address: https://github.com/zhoumengkang/php/tree/master/php-webserver/dynamic
If you want to run this demo you need to do the following
1. config.php
the project root directory in the modificationWEB_ROOT
2. Compile cgi-demo\user.c
, compile the command gcc -o user.cgi user.c
, and then user.cgi
put the file under the root directory of your configured project
3. In the terminal execution php start.php
, so that the Web server is started
4. Through http://localhost:9003/user.cgi?id=1 You can access the following effect
In fact, only on the basis of static server to do some CGI judgment is the request of forwarding processing, the github of the three files on the code merged into a file to facilitate everyone to watch
PHP <?php class Web_config {//Listener port number Const Port = 9003;
Project root directory Const WEB_ROOT = "/users/zhoumengkang/documents/html";
The system-supported CGI program's file name extension 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 () {$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 ($filename));
else {return $this->not_found (); }/** * Set environment variable to CGI program using * @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); }/** * To determine whether the requested URI is a valid CGI resource * @param $uri * @return bool/Private Function Cgi_check ($uri) {$info = Pathin
Fo ($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 () {$content = "
The above is the entire content of this article, I hope you like.