Created
February 13, 2015 09:38
-
-
Save forthxu/aee4a8c15bf55c829c56 to your computer and use it in GitHub Desktop.
PHP开http服务
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <?php | |
| trait http{ | |
| private $max_read = 8192; | |
| private $software = 'Kws/1.0 (By King)'; | |
| private $charset = 'utf-8'; | |
| private $headers = [ | |
| '_http'=>'HTTP/1.1 %d %s', | |
| '_type'=>'Content-type:%s', | |
| '_time'=>'Date:%s', | |
| '_length'=>'Content-Length:%d', | |
| '_connect'=>'Connection:keep-alive', | |
| '_sorfware'=>'Server:%s' | |
| ]; | |
| private $status = [ | |
| // Informational 1xx | |
| 100 => 'Continue', | |
| 101 => 'Switching Protocols', | |
| // Success 2xx | |
| 200 => 'OK', | |
| 201 => 'Created', | |
| 202 => 'Accepted', | |
| 203 => 'Non-Authoritative Information', | |
| 204 => 'No Content', | |
| 205 => 'Reset Content', | |
| 206 => 'Partial Content', | |
| // Redirection 3xx | |
| 300 => 'Multiple Choices', | |
| 301 => 'Moved Permanently', | |
| 302 => 'Found', // 1.1 | |
| 303 => 'See Other', | |
| 304 => 'Not Modified', | |
| 305 => 'Use Proxy', | |
| // 306 is deprecated but reserved | |
| 307 => 'Temporary Redirect', | |
| // Client Error 4xx | |
| 400 => 'Bad Request', | |
| 401 => 'Unauthorized', | |
| 402 => 'Payment Required', | |
| 403 => 'Forbidden', | |
| 404 => 'Not Found', | |
| 405 => 'Method Not Allowed', | |
| 406 => 'Not Acceptable', | |
| 407 => 'Proxy Authentication Required', | |
| 408 => 'Request Timeout', | |
| 409 => 'Conflict', | |
| 410 => 'Gone', | |
| 411 => 'Length Required', | |
| 412 => 'Precondition Failed', | |
| 413 => 'Request Entity Too Large', | |
| 414 => 'Request-URI Too Long', | |
| 415 => 'Unsupported Media Type', | |
| 416 => 'Requested Range Not Satisfiable', | |
| 417 => 'Expectation Failed', | |
| // Server Error 5xx | |
| 500 => 'Internal Server Error', | |
| 501 => 'Not Implemented', | |
| 502 => 'Bad Gateway', | |
| 503 => 'Service Unavailable', | |
| 504 => 'Gateway Timeout', | |
| 505 => 'HTTP Version Not Supported', | |
| 509 => 'Bandwidth Limit Exceeded' | |
| ]; | |
| private $server = []; | |
| //socket 套接字 | |
| private $socket; | |
| //accept | |
| private $accept; | |
| //绑定端口 | |
| private $ip; | |
| //callback | |
| private $call; | |
| //end header | |
| private $crlf = "\r\n\r\n"; | |
| //html | |
| private $html = []; | |
| //request | |
| private $request = []; | |
| function bind($ip,$port,$type='tcp'){ | |
| $this->server['ip'] = $ip; | |
| $this->server['port'] = $port; | |
| $stype = sprintf('%s://%s:%d',$type,$ip,$port); | |
| $this->socket = stream_socket_server($stype,$error,$errno); | |
| if($this->socket) return true; | |
| if(!$this->socket) return false; | |
| } | |
| function accept(){ | |
| $this->accept = @stream_socket_accept($this->socket,-1,$this->ip); | |
| stream_set_blocking($this->socket,0); | |
| if($this->accept !== false) return true; | |
| } | |
| function close(){ | |
| if($this->accept) { | |
| @fclose($this->accept); | |
| } | |
| } | |
| function sendReplys(){ | |
| $headers = []; | |
| $pre = headers_list(); | |
| foreach($pre as $key=>$value){ | |
| if(strpos(strtolower($value),'content-type')===0){ | |
| unset($pre[$key]); | |
| $type = substr($value,strpos($value,':')+1,strlen($value)); | |
| } | |
| } | |
| if(!empty($type)){ | |
| $headers['type'] = $type; | |
| }else{ | |
| $headers['type'] = sprintf('text/html;charset=%s',$this->charset); | |
| } | |
| $body = !empty($this->html) ? join(null,$this->html) : null; | |
| $headers['status'] = http_response_code(); | |
| $this->server['headers'][] = sprintf($this->headers['_http'],$headers['status'],$this->status[$headers['status']]); | |
| $this->server['headers'][] = sprintf($this->headers['_type'],$headers['type']); | |
| $this->server['headers'][] =sprintf($this->headers['_time'],gmdate("D, d M Y H:i:s T")); | |
| $this->server['headers'][] =sprintf($this->headers['_length'],strlen($body)); | |
| $this->server['headers'][] = $this->headers['_connect']; | |
| $this->server['headers'][] = sprintf($this->headers['_sorfware'],$this->software); | |
| $end = array_pop($this->server['headers']); | |
| $this->server['headers'] = array_merge($this->server['headers'],$pre); | |
| array_push($this->server['headers'],$end); | |
| $str = join("\r\n",$this->server['headers']).$this->crlf; | |
| fputs($this->accept,$str,strlen($str)); | |
| if(!empty($this->html)) fputs($this->accept,$body,strlen($body)); | |
| } | |
| function work(){ | |
| ob_start(); | |
| $this->run(); | |
| $app = ob_get_clean(); | |
| $this->send($app); | |
| } | |
| function send($data=null){ | |
| $this->html[] = $data; | |
| } | |
| function request(){ | |
| $uri = fread($this->accept,$this->max_read); | |
| $request = explode("\r\n", $uri); | |
| $this->request['_uri'] = array_shift($request); | |
| foreach ($request as $key => $value) { | |
| if(strpos($value,":")){ | |
| $name = sprintf('HTTP_%s',str_replace('-','_',strtoupper(substr($value,0,strpos($value,":"))))); | |
| $this->request[$name] = substr($value,strpos($value,':')+1,strlen($value)); | |
| } | |
| } | |
| $post = explode(" ", $uri)[0]; | |
| if($post=='POST') { | |
| //post处理 | |
| $this->server['post'] = end($request); | |
| } | |
| } | |
| function php_server(){ | |
| unset($_SERVER,$_REQUEST,$_GET,$_POST); | |
| $ip = explode(":",$this->ip); | |
| $request_uri = explode(' ',$this->request['_uri'])[1]; | |
| $path = parse_url($request_uri); | |
| $this->server['query'] = isset($path['query']) ? $path['query'] : null; | |
| $SERVER["DOCUMENT_ROOT"] = dirname(__FILE__); | |
| $SERVER['REMOTE_ADDR'] = $ip[0]; | |
| $SERVER["REMOTE_PORT"] = $ip[1]; | |
| $SERVER["SERVER_NAME"] = $this->server['ip']; | |
| $SERVER["REQUEST_URI"] = $request_uri; | |
| $SERVER["QUERY_STRING"] = $this->server['query']; | |
| $SERVER["SCRIPT_NAME"] = basename(__FILE__); | |
| $SERVER["PHP_SELF"] = __FILE__; | |
| $SERVER["SCRIPT_FILENAME"] = __FILE__; | |
| $SERVER["SERVER_PORT"] = $this->server['port']; | |
| $SERVER["SERVER_SOFTWARE"] = $this->software; | |
| $SERVER["SERVER_PROTOCOL"] = explode(' ', $this->request['_uri'])[2]; | |
| $SERVER["REQUEST_METHOD"] = explode(' ', $this->request['_uri'])[0]; | |
| $SERVER["REQUEST_TIME_FLOAT"] = gettimeofday(true); | |
| $SERVER["REQUEST_TIME"] = time(); | |
| $_SERVER = array_merge($SERVER,$this->request); | |
| unset($_SERVER['_uri']); | |
| } | |
| function php_cookie(){ | |
| if(empty($this->request['HTTP_COOKIE'])) return; | |
| $_COOKIE=[]; | |
| $cookie = explode(';',$this->request['HTTP_COOKIE']); | |
| foreach ($cookie as $key => $value) { | |
| if(!strpos($value,'=')) return; | |
| $_COOKIE[trim(substr($value,0,strpos($value,'=')),' ')] = urldecode(substr($value,strpos($value,'=')+1,strlen($value))); | |
| } | |
| $_COOKIE = array_merge([],$_COOKIE); | |
| } | |
| function php_get(){ | |
| if(empty($this->server['query'])) return; | |
| $_GET = []; | |
| $get = explode('&',$this->server['query']); | |
| foreach ($get as $key => $value) { | |
| if(!strpos($value,'=')) return; | |
| $_GET[trim(substr($value,0,strpos($value,'=')),' ')] = urldecode(substr($value,strpos($value,'=')+1,strlen($value))); | |
| } | |
| $_REQUEST = $_GET; | |
| } | |
| function php_post(){ | |
| if(empty($this->server['post'])) return; | |
| $_POST = []; | |
| $get = explode('&',$this->server['post']); | |
| foreach ($get as $key => $value) { | |
| if(!strpos($value,'=')) return; | |
| $_POST[trim(substr($value,0,strpos($value,'=')),' ')] = urldecode(substr($value,strpos($value,'=')+1,strlen($value))); | |
| } | |
| $_REQUEST = $_POST; | |
| } | |
| function php_handler(){ | |
| //php server 支持 | |
| $this->php_server(); | |
| //php cookie 支持 | |
| $this->php_cookie(); | |
| //php get 支持 | |
| $this->php_get(); | |
| //php post 支持 | |
| $this->php_post(); | |
| } | |
| private function start(){ | |
| //解析request | |
| $this->request(); | |
| $this->php_handler(); | |
| /**user**/ | |
| $this->work(); | |
| /**end*/ | |
| $this->sendReplys(); | |
| } | |
| function dispatch(){ | |
| while(true){ | |
| usleep(1); | |
| $this->accept(); | |
| $pid = pcntl_fork(); | |
| if($pid==-1){ | |
| exit('create pcntl faild!'); | |
| }elseif($pid){ | |
| $this->start(); | |
| break; | |
| } | |
| $this->close(); | |
| } | |
| } | |
| } | |
| if(version_compare(PHP_VERSION, '5.4.0', '<')) | |
| die('php版本小于5.4不支持'); | |
| if(substr(strtolower(PHP_OS),0,3)=='win' || substr(strtolower(PHP_SAPI),0,3)!=='cgi') | |
| die('请在linux下用cgi方式运行~'); | |
| if(!extension_loaded('pcntl')) | |
| die('需要安装pcntl拓展'); | |
| /** | |
| * expmple | |
| */ | |
| class server{ | |
| use http; | |
| function run(){ | |
| //要工作的php代码~ | |
| phpinfo(); | |
| } | |
| } | |
| $http = new server; | |
| $http->bind('0.0.0.0',1131); | |
| $http->dispatch(); | |
| ?> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment