【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}\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();
效果图: