本身動手用PHP編寫一個簡單的HTTP Server(單進程版)

本身動手用PHP編寫一個簡單的HTTP Server(單進程版)

HTTP協議個人簡化版理解就是電腦上瀏覽器向服務器發送一個預先定義好的文本(Http Request)
而後服務器端處理一下(一般是從硬盤讀取一個後綴名爲html的文件),而後再把這個文件
經過文本方式發回去(Http Response),就這麼簡單。php

惟一麻煩的是我得請操做系統給我創建Http層下面的TCP鏈接通道,由於全部的文本數據都得
經過TCP管道接收和發送,這個通道是用socket創建的。html

  • 僞代碼以下web

socketMain= socket(...)
bind(socketMain,主機的IP和端口號)
listen(socketMain,...)

無限循環
while(true) {
    socketAccept = accept(socketMain,....)
    receive(socketAccept,....)
    send(socketAccept...)
    close(socketAccept...)

}
  • 僞代碼解釋瀏覽器

這些socket,bind,listen,accept都是操做系統提供的接口,咱們要作的就是把這些進行
組裝;如今80或者其餘端口監聽,而後進入無限循環,若是有請求進來,就接受(accept),建立新的socket,最後經過這個socket來接收和發送Http數據。服務器

  • 實現的php代碼以下socket

只實現了當前目錄下的html與jpg圖片的解析處理,原理都相似。this

<?php


set_time_limit(0);

class HttpServer
{
    private $ip = '127.0.0.1';
    private $port = 9996;

    private $_socket = null;

    public function __construct()
    {
        $this->_socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
        if ($this->_socket === false) {
            die(socket_strerror(socket_last_error($this->_socket)));
        }
    }

    public function run()
    {
        socket_bind($this->_socket, $this->ip, $this->port);
        socket_listen($this->_socket, 5);
        while(true) {
            $socketAccept = socket_accept($this->_socket);
            $request = socket_read($socketAccept, 1024);
            echo $request;
            socket_write($socketAccept, 'HTTP/1.1 200 OK'.PHP_EOL);
            socket_write($socketAccept, 'Date:'.date('Y-m-d H:i:s').PHP_EOL);

            $fileName = $this->getUri($request);
            $fileExt = preg_replace('/^.*\.(\w+)$/', '$1', $fileName);
            $fileName = __DIR__.'/'.$fileName;
            switch ($fileExt) {
                case "html":
                    //set content type
                    socket_write($socketAccept, 'Content-Type: text/html'.PHP_EOL);
                    socket_write($socketAccept, ''.PHP_EOL);
                    $fileContent = file_get_contents($fileName);
                    socket_write($socketAccept, $fileContent, strlen($fileContent));
                    break;
                case "jpg":
                    socket_write($socketAccept, 'Content-Type: image/jpeg'.PHP_EOL);
                    socket_write($socketAccept,''.PHP_EOL);
                    $fileContent = file_get_contents($fileName);
                    socket_write($socketAccept, $fileContent, strlen($fileContent));
                    break;
            }
            socket_write($socketAccept, 'web serving', strlen('web serving'));
            socket_close($socketAccept);

        }

    }

    protected function getUri($request = '')
    {
        $arrayRequest = explode(PHP_EOL, $request);
        $line = $arrayRequest[0];
        $file = trim(preg_replace('/(\w+)\s\/(.*)\sHTTP\/1.1/i','$2', $line));
        return $file;
    }


    public function close()
    {
        socket_close($this->_socket);
    }





}
$httpServer = new HttpServer();
$httpServer->run();
相關文章
相關標籤/搜索