So implementieren Sie einen dynamischen Webserver in PHP

墨辰丷
Freigeben: 2023-03-30 17:04:01
Original
2772 Leute haben es durchsucht

In diesem Artikel wird hauptsächlich die Methode zur Implementierung eines dynamischen Webservers in PHP vorgestellt. Ich hoffe, dass er für alle hilfreich ist.

Wenn Sie einen Webserver implementieren möchten, müssen Sie ein allgemeines Verständnis der Funktionsprinzipien des Webservers haben. Beginnen wir mit einem statischen Textserver als Beispiel:

1. Der Client sendet eine HTTP-Anfrage an den Server 9002, dann in Die Adresse des eigenen Testzugriffs dieser Maschine lautet http://localhost:9002/1.html.

2. Der Server überwacht Port 9002, sodass er nach Erhalt der Anfrage die URI-Ressource, auf die in der Anfrage zugegriffen werden muss, vom http-Head im Webverzeichnis abrufen kann. Standort.

3. Der Server liest die Ressourcendatei, auf die zugegriffen werden muss, füllt sie dann in die http-Entität und gibt sie an den Client zurück.

Das schematische Diagramm sieht wie folgt aus:

php
<?php
class web_config {
 // 监听的端口号
 const PORT = 9003;
 // 项目根目录
 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){
 // 静态 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";
 // 静态文件的处理
 if (file_exists($filename)) {
 return $this->add_header(file_get_contents($filename));
 } else {
 return $this->not_found();
 }
 }
 /**
 * 404 返回
 * @return string
 */
 private function not_found(){
 $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;
 }
 /**
 * 加上头信息
 * @param $string
 * @return string
 */
 private function add_header($string){
 return "HTTP/1.1 200 OK\r\nContent-Length: ".strlen($string)."\r\nServer: mengkang\r\n\r\n".$string;
 }
}
$server = new server("127.0.0.1", web_config::PORT);
Nach dem Login kopieren

Der Code wurde auf Github https://github.com/zhoumengkang/php hochgeladen /tree/master/php- webserver/static

Wie im obigen Code erwähnt, wird ein statischer Webserver gestartet, solange die Datei im Terminal ausgeführt wird.

Das Bild unten ist ein Screenshot von mir, wie ich auf die 1.jpg-Datei in meinem Webverzeichnis zugreife

Der einfache statische Webserver wurde wie folgt fertiggestellt Die Frage ist, wie man dafür sorgen kann, dass die Ausgabe dynamischer Inhalte unterstützt wird. Müssen wir nur ein bestimmtes Programm innerhalb des Webservers ausführen und das Ergebnis an den Client zurückgeben? Aber auf diese Weise wird der Webservercode mit dem Geschäftscode gekoppelt. Wie kann ein Webserver gelöst werden, der in verschiedenen Geschäftsszenarien verwendet werden kann?

Das Aufkommen von CGI hat dieses Problem gelöst. Was ist CGI? Die folgende Passage wird kopiert:

CGI ist ein Schnittstellenstandard zwischen externen Anwendungen (CGI-Programmen) und Webservern. Es handelt sich um ein Verfahren zur Übertragung von Informationen zwischen CGI-Programmen und Webservern. Die CGI-Spezifikation ermöglicht es Webservern, externe Programme auszuführen und ihre Ausgabe an Webbrowser zu senden. CGI verwandelt den Satz einfacher statischer Hypermedia-Dokumente in ein völlig neues interaktives Medium.

Um ein konkretes Beispiel zu nennen: Die von uns verwendete globale Variable <span style="max-width:90%">$_SERVER[&#39;QUERY_STRING&#39;]</span> von PHP wird vom Webserver über das CGI-Protokoll übergeben. Vielleicht erinnern Sie sich zum Beispiel daran, dass der Fastcgi-Konfigurationscode

in Nginx wie folgt lautet:

fastcgi_param  
QUERY_STRING      
 $query_string;
Nach dem Login kopieren

Ja, Nginx übergibt seine globale Variable <span style="font-family:NSimsun">$query_string</span> an die Umgebungsvariable von fastcgi_param.

Im Folgenden verwenden wir auch CGIs <span style="font-family:NSimsun">QUERY_STRING</span> als Brücke, um die vom Client angeforderten Informationen in der URI an das CGI-Programm weiterzuleiten. Speichern Sie <span style="font-family:NSimsun">putenv</span> in der Umgebungsvariablen der Anfrage über <span style="font-family:NSimsun">QUERY_STRING</span>.

Wir sind uns einig, dass die Ressourcen, auf die im Webserver zugegriffen wird, <span style="font-family:NSimsun">.cgi</span> sind. Das Suffix zeigt den dynamischen Zugriff an. Dies ähnelt ein wenig der Konfiguration des Speicherorts in Nginx, um PHP-Skripte zu finden. Es ist alles eine Regel, um zu prüfen, ob ein CGI-Programm angefordert werden soll. Um ihn vom Webserver zu unterscheiden, habe ich ein CGI-Programm in C geschrieben, um Benutzerinformationen abzufragen und Benutzerinformationen basierend auf der Benutzer-ID abzufragen.

Die ungefähre Zugriffslogik ist wie unten dargestellt

Wenn Sie die Demo ausführen möchten, müssen Sie die folgenden Vorgänge ausführen

1. Ändern<span style="max-width:90%">config.php</span> Das Projektstammverzeichnis in <span style="font-family:NSimsun">WEB_ROOT</span>

2. Kompilieren Sie <span style="font-family:NSimsun">cgi-demouser.c</span>, kompilieren Sie den Befehl <span style="font-family:NSimsun">gcc -o user.cgi user.c</span> und legen Sie dann die Datei <span style="font-family:NSimsun">user.cgi</span> ab unter dem von Ihnen konfigurierten Projektstammverzeichnis

3. Führen Sie <span style="font-family:NSimsun">php start.php</span> im Terminal aus, damit der Webserver startet

4. Pass http://localhost:9003/user.cgi?id=1 Sie können auf den folgenden Effekt zugreifen und ihn sehen

Tatsächlich ist es nur auf dem statischen Server. Auf der Grundlage einiger CGI-Beurteilungen handelt es sich um die Verarbeitung der Anforderungsweiterleitung, und die Codes der drei Dateien auf Github wurden in einer Datei zusammengeführt, damit jeder sie sehen kann

php
<?php
class web_config {
 // 监听的端口号
 const PORT = 9003;
 // 项目根目录
 const WEB_ROOT = "/Users/zhoumengkang/Documents/html";
 // 系统支持的 cgi 程序的文件扩展名
 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){
 // 静态 GET /1.html HTTP/1.1 ...
 // 动态 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);
 }
 // 静态文件的处理
 if (file_exists($filename)) {
 return $this->add_header(file_get_contents($filename));
 } else {
 return $this->not_found();
 }
 }
 /**
 * 设置环境变量 给 cgi 程序使用
 * @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);
 }
 }
 /**
 * 判断请求的 uri 是否是合法的 cgi 资源
 * @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 返回
 * @return string
 */
 private function not_found(){
 $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;
 }
 /**
 * 加上头信息
 * @param $string
 * @return string
 */
 private function add_header($string){
 return "HTTP/1.1 200 OK\r\nContent-Length: ".strlen($string)."\r\nServer: mengkang\r\n\r\n".$string;
 }
}
$server = new server("127.0.0.1", web_config::PORT);
Nach dem Login kopieren

Zusammenfassung: Das Obige ist dieser Artikel. Der gesamte Inhalt dieses Artikels soll für das Studium aller hilfreich sein.

Verwandte Empfehlungen:

Die Funktion der Verwendung von Curl zum Fälschen von IP in PHP

So verwenden Sie das MagickWand-Modul, um Bilder zu bearbeiten und Wasserzeichen in PHP hinzuzufügen

smarty self Definition und Nutzung definierter Ressourcen

Das obige ist der detaillierte Inhalt vonSo implementieren Sie einen dynamischen Webserver in PHP. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Quelle:php.cn
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage
Über uns Haftungsausschluss Sitemap
Chinesische PHP-Website:Online-PHP-Schulung für das Gemeinwohl,Helfen Sie PHP-Lernenden, sich schnell weiterzuentwickeln!