需要 pthreads 扩展
php 命令行模式运行
写的比较急,没时间优化,有时间我会抽空优化一下
来自源地址: http://www.haowei.me/archives/1009.html socket = $socket; $this->arguments = $arguments; if(!isset($this->arguments['servertokens'])) $this->arguments['servertokens'] = 'off'; } public function run() { date_default_timezone_set('utc'); $clients = 1; $maxrequests = !isset($this->arguments['maxrequests'])? intval($this->arguments['maxrequests']): 100; $timeout = 5; $connfd = socket_accept($this->socket); socket_set_option($connfd, sol_socket, so_rcvtimeo, array('sec' => $timeout, 'usec' => 0)); $session = 1; while($session) { $buffer = ''; while (( $buffer .= socket_read($connfd, 1024, php_binary_read) )) if(strpos($buffer, \r\n\r\n) !== false) break; if($buffer == '') { socket_close($connfd); $session = 0; }else{ $availablerequests = $maxrequests - $clients; $clients++; $i = 0; $headers = array(); array_push($headers, 'http/1.1 200 ok'); array_push($headers, 'date: '. gmtdate()); array_push($headers, 'server: php-cli/1.0'); array_push($headers, 'content-type: text/html; charset=utf-8'); array_push($headers, 'connection: close'); if($this->arguments['servertokens'] == 'on') $headers[2] = 'server: php-cli'; $buffer = explode(\r\n, $buffer); $http_user_agent = ''; $http_request_method = ''; $http_request_file = ''; $http_protocol = ''; $extension = ''; $mime_types = ''; $this->octet_stream = false; foreach($buffer as $line) { $pattern = '/(get|post)\s\/(.*)\s(http\/1\.[0-1])$/'; if(preg_match($pattern, $line)) { $http_request_method = preg_replace($pattern, '\\1', $line); $http_request_file = preg_replace($pattern, '\\2', $line); $http_protocol = preg_replace($pattern, '\\3', $line); } $pattern = '/^user\-agent: (.+)$/'; if(preg_match($pattern, $line)) { $http_user_agent = preg_replace($pattern, '\\1', $line); } } $local_request_file = $this->arguments['documentroot'].'/'. $http_request_file; if(file_exists($local_request_file) && is_file($local_request_file)) $extension = pathinfo($local_request_file, pathinfo_extension); if(file_exists($local_request_file)) { $array_key_exists = array_key_exists($extension, $this->arguments['mimetypes']); if(is_file($local_request_file)) { if($array_key_exists) { $mime_types = $this->arguments['mimetypes'][$extension]; $headers[3] = sprintf('content-type: %s; charset=%s', $mime_types, 'utf-8'); }else{ $this->octet_stream = true; $headers[3] = sprintf('content-type: application/octet-stream'); array_push($headers, 'accept-ranges: bytes'); array_push($headers, 'accept-length: '.filesize($local_request_file)); array_push($headers, 'content-disposition: attachment; filename='.basename($local_request_file)); } } } $html = ''; $code = ''; $this->httpstatuscode($local_request_file, $headers, $html, $code); if($availablerequests > 0) { $headers[4] = connection: keep-alive; $headers[5] = 'keep-alive: timeout='.$timeout.', max='.$maxrequests; } $headers[6] = 'content-length: '. strlen($html); $response = array( 'header'=> implode(\r\n, $headers) . \r\n, 'html'=> $html); socket_write($connfd, implode(\r\n, $response)); if($availablerequests socket_close($connfd); $session = 0; } $length = strlen($html); socket_getpeername($connfd, $address, $port); logs(sprintf('%s:%.0f -- %s %s %s %s %.0f - %s', $address, $port, $http_request_method, '/'.$http_request_file, $http_protocol, $code, $length, $http_user_agent)); //logs('times '. intval($clients - 1), false); } } } public function error_page($statuscode, $servertokens) { $httpstatus = array('403'=> '403 forbidden', '404'=> '404 not found'); $string = %s %s %s ; if(!in_array($servertokens, array('on', 'off'))) $servertokens = 'off'; return (string) sprintf($string, $httpstatus[$statuscode], $httpstatus[$statuscode], $servertokens == 'off' ? 'php-cli/1.0' : 'php-cli'); } public function httpstatuscode($file, &$headers, &$html, &$code) { $code = '200'; if(!file_exists($file)) { $headers[0] = 'http/1.1 404 not found'; $html = $this->error_page('404', $this->arguments['servertokens']); $code = '404'; return 0; } if(is_dir($file)){ $find = false; $directoryindex = $this->arguments['directoryindex']; if(empty($directoryindex)) { $headers[0] = 'http/1.1 403 forbidden'; $code = '403'; }else{ $list = explode(' ', $directoryindex); foreach($list as $index) { if(file_exists($file .'/'. $index)) { $file .= '/'. $index; if(file_exists($file) && is_file($file)) $extension = pathinfo($file, pathinfo_extension); $array_key_exists = array_key_exists($extension, $this->arguments['mimetypes']); if($array_key_exists) { $mime_types = $this->arguments['mimetypes'][$extension]; }else{ $this->otect_stream = true; $headers[3] = sprintf('content-type: application/octet-stream'); array_push($headers, 'accept-ranges: bytes'); array_push($headers, 'accept-length: '.filesize($local_request_file)); array_push($headers, 'content-disposition: attachment; filename='.basename($local_request_file)); } $find = true; break; } } } if(!$find) { $html = $this->error_page('403', $this->arguments['servertokens']); }else{ if(!$this->octet_stream) $headers[3] = sprintf('content-type: %s; charset=%s', $mime_types, 'utf-8'); $html = $this->get_local_handle_buffer($file); } return -1; }else{ $html = $this->get_local_handle_buffer($file); } return 1; } public function get_local_handle_buffer($file) { $handle = fopen($file, 'rb'); return $this->get_buffer($handle); } public function get_buffer($handle) { $buffer = ''; if(!is_resource($handle)) return null; while(!feof($handle)) $buffer .= fgets($handle, 1024); fclose($handle); return $buffer; } }function gmtdate() { return (string) date('d, d m y h:i:s'). ' gmt';}function logs($string, $perfix = true) { ob_start(); echo $perfix ? sprintf([ %s ] %s\n, date('d-m-y h:i:s'), $string) : sprintf(\0\0[ %s ]\n, $string); ob_end_flush();}$mime_types = array('htm'=> 'text/html','html'=> 'text/html','jpg'=> 'image/jpeg','jpeg'=> 'image/jpeg','png'=> 'image/png','js'=> 'text/javascript','css'=> 'text/css','xml'=> 'text/xml');$conf = array('mimetypes'=> $mime_types,'servertokens'=> 'on','maxrequests'=> 100,'timeout'=> 15,'listen'=> 8080,'documentroot'=> '/home/www', 'directoryindex'=> 'index.htm index.html');error_reporting(e_all);logs('initializing the operating environment');sleep(1);set_time_limit(0);logs('initializing php-cli execution timeout');sleep(1);$socket = socket_create(af_inet, sock_stream, sol_tcp);logs('initializing the socket');sleep(1);logs('initialization bind local address any ip address');sleep(1);$int = socket_bind($socket, '0.0.0.0', $conf['listen']);logs('initialization bind local port '.$conf['listen']);if(!$int){ logs($conf['listen'].' port is occupied by other services'.\n); exit(0);}sleep(1);socket_listen($socket, 1024);logs('opening a socket listening');sleep(1);logs('waiting for clients to access');echo \n;$i = 0;while(1) { $pthread[$i] = new pthread($socket, $conf); $pthread[$i]->start(); $pthread[$i]->join();}
复制代码