使用PHP實現一個簡單web服務器

web服務器是基於http協議,將對應的文件傳輸給客戶端的服務器。

web服務器是什麼

web服務器是基於http協議,將對應的文件傳輸給客戶端的服務器。

HTTP協議

http 協議的請求及響應方式設計
http 協議的請求及響應方式設計
http請求信息的結構

在這裏插入圖片描述

請求信息分爲請求行、消息頭、消息體等3部分。

http響應信息結構

在這裏插入圖片描述
響應信息格式如上圖。

有了對http協議的瞭解就可以開始來看下面的代碼了。

使用方法

1、 啓動服務端 php http_server.php
2、打開瀏覽器輸入127.0.0.1:
由於 php沒有多線程,不能有效管理子進程。select、 i/o 複用epol,沒辦法高效
源碼 http_server.php

<?php


if ($argc != 2) {
    $msg = sprintf("Usage: %s <port>", $argv[0]);
    die($msg);
}
$host = "127.0.0.1";
$port = $argv[1];

if (($serv_sock = socket_create(AF_INET, SOCK_STREAM, SOL_TCP)) < 0) {
    die("socket_create() error: ". socket_strerror($serv_sock));
}


if (($ret = socket_bind($serv_sock, $host, $port)) < 0) {
     die("socket_bind() error: ". socket_strerror($ret));
}

if (($ret = socket_listen($serv_sock, 4)) < 0) {
      die("socket_listen() error: ". socket_strerror($ret));
}
echo "服務啓動成功 {$host}:{$port}\n";

while (1) {
   if (($clnt_sock = socket_accept($serv_sock)) < 0) {
         echo "socket_accept() error: ". socket_strerror($clnt_sock), "\n";
         break;
   } else {
       $str = str_pad('', 1024);
       echo "Connection Request {$str} \n";
       if (!request_handler($clnt_sock)) {

       }
       socket_close($clnt_sock);
   }
}
socket_close($serv_sock);




function request_handler($clnt_sock)
{
   $req_buf = socket_read($clnt_sock, 4096);
   echo "請求信息:\n";
   echo $req_buf;
   $req_info = explode( "\n" ,  $req_buf);
   $req_head = $req_info[0];
   if (strpos($req_head, "HTTP/") === false) {
       send_error($clnt_sock);
       return false;
   }

   $req_head_info = explode(" /" , $req_head);
   if (empty($req_head_info[0])) {
        send_error($clnt_sock, "http格式錯誤");
       return false;
   }
   $method = $req_head_info[0];

   $file_protocol = explode(' ', $req_head_info[1]);
   $file_name = $file_protocol[0];
   $file_protocol = $file_protocol[1];
   $contype = content_type($file_name);
   send_data($clnt_sock, $file_name, $contype);


}

function get_ext($file_name)
{
    $file_info = explode('.',$file_name);
    $ext = end($file_info);
    return $ext;
}

function content_type($file_name)
{
    $ext = get_ext($file_name);
    if ($ext == "php" || $ext == "html" || $ext == "htm") {
        return "text/html";
    } else if ($ext == "jpg" || $ext == "jpeg") {
            return "image/jpeg";
    }else if ($ext == "png") {
            return "image/jpeg";
    } else {
        return "text/html";
    }
}

function send_data($clnt_sock, $file_name, $contype, $content = "")
{
    $http_code = "200 OK";
    if (file_exists($file_name)) {
        $ext = get_ext($file_name);

        if ($ext == "php") {
            ob_start();
            include $file_name;
            $content = ob_get_contents();
            ob_end_clean();
        } else if($ext == "html" || $ext == "htm") {
           $content = file_get_contents($file_name);
        }
    } else {
        $content = "<html><head><title>404 not found</title></head><body style=\"text-align:center\"><span>404 not found</span></body></html>";
        $http_code = 404;
    }

    if (empty($content)) {
        $content  = "<html><head><title>PHP WEB 響應</title></head><body>收到信息".date("Y-m-d H:i:s")."</body></html>";
    }
    $response = "HTTP/1.1 {$http_code}\r\n";
    $response  .= "Server: PHP Web Server \r\n";
    $response .= "Content-lenth:".strlen($content)."\r\n";
    $response .= "Content-type:{$contype};charset=utf-8\r\n\r\n";
    $response .= $content;
       echo $response,"\n";
  $clnt_write = socket_write($clnt_sock, $response);

}


function send_error($clnt_sock, $content = "")
{
  $file_name = "";
  $html_content  = "<html><head><title>PHP WEB 響應</title></head><body>出錯了{$content}</body></html>";
  send_data($clnt_sock, $file_name, $html_content);
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章