专栏首页PHP修行之路【php socket通讯】php实现http服务 php中连接tcp服务的三种方式

【php socket通讯】php实现http服务 php中连接tcp服务的三种方式

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}\r\n";
        $header .= "Date: ".gmdate('D, d M Y H:i:s T')."\r\n";
        $header .= "Content-Type: {$content_type}\r\n";
        $header .= "Content-Length: ".strlen($content)."\r\n\r\n";//必须2个\r\n表示头部信息结束
        $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

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 调试location指令时,直接让location输出文本

    有时候我们调试location指令时希望location指令能够直接输出文本,这样能够方便我们进行调试。这时我们可以使用echo模块实现,但是大多数情况我们没有...

    码缘
  • 【多进程】php实现 master-worker 守护多进程模式

    执行命令 kill 65,杀死进程 65 则master_process 进程会再自动开启一个子进程

    码缘
  • 【php设计模式】代理模式

    主要解决在直接访问对象时带来的问题,比如说:要访问的对象在远程的机器上。在面向对象系统中,有些对象由于某些原因(比如对象创建开销很大,或者某些操作需要安全控...

    码缘
  • flask blueprint 蓝图与 url_for 的使用(微信报修小程序源码讲解五)

    蓝图 :blueprint 中文译作蓝图,是 flask 模块化的工具 ,对于一个好的应用程序来说 ,应该有很多个蓝图构成 。

    热心的程序员
  • sun.net.www.protocol.http.HttpURLConnection cannot be cast to javax.net.ssl.HttpsURLConnection 异常的处理

    sun.net.www.protocol.http.HttpURLConnection cannot be cast to javax.net.ssl.Http...

    凯哥Java
  • WSAAsyncSelect 消息模型

    select 模型虽然可以管理多个socket,但是它涉及到一个时机的问题,select模型会针对所管理的数组中的每一个socket循环检测它管理是否在对应的数...

    Masimaro
  • python时间与日期处理一次看个够(time、datetime、calendar)

    python中常常会遇见时间、日期相关的处理,python标准库其实就提供了非常强大的处理能力,它们是time、datetime、calendar标准库,下面是...

    小草AI
  • 基于mpvue开发微信小程序,vue能用的,用mpvue哪些情况不能用

    杭州前端工程师
  • 新闻动态|文青热来袭,优图人脸识别助力跨越时空重温五四

      黄景瑜撞脸徐志摩,杨子姗撞脸周璇……今天是五四青年节,在微博上杨紫、张一山、徐浩等等明星纷纷发了与自己撞脸的历史文艺青年对比图。原来,他们都在玩一款测算与历...

    优图实验室
  • 每周学点大数据 | No.56推荐系统概述

    NO.56 推荐系统概述 Mr. 王:在现在的网络购物平台和电影、图书分享平台中,还有一类非常广泛存在的机制——推荐机制。 小可:在我打开的购物网站右侧经常有...

    灯塔大数据

扫码关注云+社区

领取腾讯云代金券