zoukankan      html  css  js  c++  java
  • 【php socket通讯】php实现http服务

    http服务是建立在tcp服务之上的,它是tcp/ip协议的应用,前面我们已经实现了tcp服务,并且使用三种不同的方式连接tcp服务

    php中连接tcp服务的三种方式

    既然http也是tcp应用层的一种,那么我们直接使用浏览器来连接tcp服务可不可以?答案是可以的,只不过连接之后直接返回给浏览器的信息,浏览器不能够正确的识别出来。那么怎么才能让浏览器正确的识别tcp服务返回的信息呢?

    这个时候我们就需要使用到http协议啦,至于http传输中都传了哪些信息可以在浏览器中 f12 查看

    目录结构:

    http_serv.php文件

    <?php
    /**
    * Http 服务器类
    */
    class Http{
        private $host;
        private $port;
        private $_root;
    
        public $mime_types = array(
            'avi' => 'video/x-msvideo',
            'bmp' => 'image/bmp',
            'css' => 'text/css',
            'doc' => 'application/msword',
            'gif' => 'image/gif',
            'htm' => 'text/html',
            'html' => 'text/html',
            'ico' => 'image/x-icon',
            'jpe' => 'image/jpeg',
            'jpeg' => 'image/jpeg',
            'jpg' => 'image/jpeg',
            'js' => 'application/x-javascript',
            'mpeg' => 'video/mpeg',
            'ogg' => 'application/ogg',
            'png' => 'image/png',
            'rtf' => 'text/rtf',
            'rtx' => 'text/richtext',
            'swf' => 'application/x-shockwave-flash',
            'wav' => 'audio/x-wav',
            'wbmp' => 'image/vnd.wap.wbmp',
            'zip' => 'application/zip',
          );
    
        /**
         * @param string $host 监听地址
         * @param int $port 监听端口
         * @param string $_root 网站根目录
        */
        public function __construct($host,$port,$_root){
            $this->host = $host;
            $this->port = $port;
            $this->_root = $_root;
        }
    
        /**
        * 启动http服务
        */
        public function start(){
            //创建socket套接字
            $socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
            //设置阻塞模式
            socket_set_block($socket);
            //为套接字绑定ip和端口
            socket_bind($socket,$this->host,$this->port);
            //监听socket
            socket_listen($socket,4);
    
            while(true)
            {
                //接收客户端请求
                if(($msgsocket = socket_accept($socket)) !== false){
                    //读取请求内容
                    $buf = socket_read($msgsocket, 9024);
                    
                    preg_match("//(.*) HTTP/1.1/",$buf,$matchs);
                    
                    preg_match("/Accept: (.*?),/",$buf,$matchss);
                    //获取接收文件类型
                    $type = explode("/",$matchss[1])[0];
    
                    if($type=="text"){
                        $content = $this->GetString($matchs[1]);
                    }else{
                        $content = $this->GetImg($matchs[1]);
                    }
    
                    socket_write($msgsocket,$content,strlen($content));
    
                    socket_close($msgsocket);
                }
            }
        }
    
        /**
         * 组装消息头信息模板
         * @param int $code 状态码
         * @param string $status 状态名称
         * @param string $content 发送的文本内容
         * @param string $content_type 发送的内容类型
         * @return string
        **/
        public function GetHeaders($code,$status,$content="",$content_type="text/html;charset=utf-8"){
            $header = '';
            $header .= "HTTP/1.1 {$code} {$status}
    ";
            $header .= "Date: ".gmdate('D, d M Y H:i:s T')."
    ";
            $header .= "Content-Type: {$content_type}
    ";
            $header .= "Content-Length: ".strlen($content)."
    
    ";//必须2个
    表示头部信息结束
            $header .= $content;
            return $header;
        }
    
        /**
        * 组装文本发送信息
         * @param string $url_path
         * @return string
        **/
        public function GetString($url_path){
            if($this->getRealPath($url_path)){
                if(is_readable($this->getRealPath($url_path))){
                    return $this->GetHeaders(200,"OK",file_get_contents($this->getRealPath($url_path)),$this->getMime($url_path));
                }else{
                    return $this->GetHeaders(401,"Unauthorized");
                }
                
            }else{
                return $this->GetHeaders(404,"Not Found");
            }
        }
    
        /**
        * 组装资源返回信息
         * @param string $url_path
         * @return string
        **/
        public function GetImg($url_path){
            if($this->getRealPath($url_path)){
    
                return $this->GetHeaders(200,"OK",file_get_contents($this->getRealPath($url_path)),$this->getMime($url_path));
            }else{
               return $this->GetHeaders(404,"Not Found");
            }
        }
    
        /**
         * 获取资源类型
         * @param string $path
         * @return mixed
         */
        public function getMime($path){
           $type = explode(".",$path);
           $mime = $this-> mime_types[$type[1]]; 
           return $mime;
        }
    
        /**
         * 获取访问资源的真实地址
         * @param $url_path
         * @return bool|string
         */
        public function getRealPath($url_path){
            return realpath($this->_root."/".$url_path);
        }
    
    }
    
    $server = new Http("127.0.0.1",3046,"wwwroot");
    $server->start();

    效果图:

     

    github地址: https://github.com/enjoysmilehappy/http_server

  • 相关阅读:
    墨者-(RCE)Apache Struts2远程代码执行漏洞(S2-032)
    Apache Struts2远程代码执行漏洞(S2-015)
    墨者-(RCE)Webmin未经身份验证的远程代码执行
    MySQL注入点写入WebShell的几种方式
    墨者-rsync未授权访问漏洞利用
    墨者-Ruby On Rails漏洞复现第二题(CVE-2019-5418)
    墨者 Ruby On Rails漏洞复现第一题(CVE-2018-3760)
    SROP利用技术
    技巧点滴
    S2-045漏洞利用脚本汇总
  • 原文地址:https://www.cnblogs.com/itsuibi/p/11139112.html
Copyright © 2011-2022 走看看