Heim  >  Artikel  >  Backend-Entwicklung  >  PHP-CLI Web 服务器

PHP-CLI Web 服务器

WBOY
WBOYOriginal
2016-07-25 08:47:371170Durchsuche
需要 pthreads 扩展
php 命令行模式运行

写的比较急,没时间优化,有时间我会抽空优化一下

来自源地址: http://www.haowei.me/archives/1009.html
  1. ini_set('display_errors', false);
  2. error_reporting(0);
  3. if(!class_exists('thread')) {
  4. logs('PHP runtime environment not support multi thread');
  5. exit(0);
  6. }
  7. if(!function_exists('mime_content_type')) {
  8. logs('PHP runtime environment not support function mime_content_type()');
  9. exit(0);
  10. }
  11. class pthread extends thread {
  12. protected $socket = null;
  13. protected $arguments = null;
  14. protected $connections = 0;
  15. protected $octet_stream = false;
  16. public function __construct($socket, $arguments = array()) {
  17. $this->socket = $socket;
  18. $this->arguments = $arguments;
  19. if(!isset($this->arguments['ServerTokens']))
  20. $this->arguments['ServerTokens'] = 'off';
  21. }
  22. public function run() {
  23. date_default_timezone_set('UTC');
  24. $clients = 1;
  25. $maxRequests = !isset($this->arguments['MaxRequests'])?
  26. intval($this->arguments['MaxRequests']):
  27. 100;
  28. $timeout = 5;
  29. $connfd = socket_accept($this->socket);
  30. socket_set_option($connfd, SOL_SOCKET, SO_RCVTIMEO, array('sec' => $timeout, 'usec' => 0));
  31. $session = 1;
  32. while($session) {
  33. $buffer = '';
  34. while (( $buffer .= socket_read($connfd, 1024, PHP_BINARY_READ) ))
  35. if(strpos($buffer, "\r\n\r\n") !== false) break;
  36. if($buffer == '') {
  37. socket_close($connfd);
  38. $session = 0;
  39. }else{
  40. $availableRequests = $maxRequests - $clients;
  41. $clients++;
  42. $i = 0;
  43. $headers = array();
  44. array_push($headers, 'HTTP/1.1 200 OK');
  45. array_push($headers, 'Date: '. gmtdate());
  46. array_push($headers, 'Server: PHP-CLI/1.0');
  47. array_push($headers, 'Content-Type: text/html; charset=utf-8');
  48. array_push($headers, 'Connection: close');
  49. if($this->arguments['ServerTokens'] == 'on')
  50. $headers[2] = 'Server: PHP-CLI';
  51. $buffer = explode("\r\n", $buffer);
  52. $http_user_agent = '';
  53. $http_request_method = '';
  54. $http_request_file = '';
  55. $http_protocol = '';
  56. $extension = '';
  57. $mime_types = '';
  58. $this->octet_stream = false;
  59. foreach($buffer as $line) {
  60. $pattern = '/(GET|POST)\s\/(.*)\s(HTTP\/1\.[0-1])$/';
  61. if(preg_match($pattern, $line)) {
  62. $http_request_method = preg_replace($pattern, '\\1', $line);
  63. $http_request_file = preg_replace($pattern, '\\2', $line);
  64. $http_protocol = preg_replace($pattern, '\\3', $line);
  65. }
  66. $pattern = '/^User\-Agent: (.+)$/';
  67. if(preg_match($pattern, $line)) {
  68. $http_user_agent = preg_replace($pattern, '\\1', $line);
  69. }
  70. }
  71. $local_request_file = $this->arguments['DocumentRoot'].'/'. $http_request_file;
  72. if(file_exists($local_request_file) && is_file($local_request_file))
  73. $extension = pathinfo($local_request_file, PATHINFO_EXTENSION);
  74. if(file_exists($local_request_file)) {
  75. $array_key_exists = array_key_exists($extension, $this->arguments['MimeTypes']);
  76. if(is_file($local_request_file)) {
  77. if($array_key_exists) {
  78. $mime_types = $this->arguments['MimeTypes'][$extension];
  79. $headers[3] = sprintf('Content-Type: %s; charset=%s', $mime_types, 'utf-8');
  80. }else{
  81. $this->octet_stream = true;
  82. $headers[3] = sprintf('Content-Type: application/octet-stream');
  83. array_push($headers, 'Accept-Ranges: bytes');
  84. array_push($headers, 'Accept-Length: '.filesize($local_request_file));
  85. array_push($headers, 'Content-Disposition: attachment; filename='.basename($local_request_file));
  86. }
  87. }
  88. }
  89. $html = '';
  90. $code = '';
  91. $this->HttpStatusCode($local_request_file, $headers, $html, $code);
  92. if($availableRequests > 0) {
  93. $headers[4] = "Connection: keep-alive";
  94. $headers[5] = 'Keep-Alive: timeout='.$timeout.', max='.$maxRequests;
  95. }
  96. $headers[6] = 'Content-Length: '. strlen($html);
  97. $response = array(
  98. 'header'=> implode("\r\n", $headers) . "\r\n",
  99. 'html'=> $html);
  100. socket_write($connfd, implode("\r\n", $response));
  101. if($availableRequests socket_close($connfd);
  102. $session = 0;
  103. }
  104. $length = strlen($html);
  105. socket_getpeername($connfd, $address, $port);
  106. logs(sprintf('%s:%.0f -- "%s %s %s" %s %.0f "-" "%s"',
  107. $address,
  108. $port,
  109. $http_request_method,
  110. '/'.$http_request_file,
  111. $http_protocol,
  112. $code,
  113. $length,
  114. $http_user_agent));
  115. //logs('times '. intval($clients - 1), false);
  116. }
  117. }
  118. }
  119. public function error_page($statusCode, $ServerTokens) {
  120. $httpStatus = array('403'=> '403 Forbidden', '404'=> '404 Not Found');
  121. $string = "
  122. %s
  123. %s


  124. %s
  125. ";
  126. if(!in_array($ServerTokens, array('on', 'off')))
  127. $ServerTokens = 'off';
  128. return (string) sprintf($string,
  129. $httpStatus[$statusCode],
  130. $httpStatus[$statusCode],
  131. $ServerTokens == 'off' ? 'PHP-CLI/1.0' : 'PHP-CLI');
  132. }
  133. public function HttpStatusCode($file, &$headers, &$html, &$code) {
  134. $code = '200';
  135. if(!file_exists($file)) {
  136. $headers[0] = 'HTTP/1.1 404 Not Found';
  137. $html = $this->error_page('404', $this->arguments['ServerTokens']);
  138. $code = '404';
  139. return 0;
  140. }
  141. if(is_dir($file)){
  142. $find = false;
  143. $directoryIndex = $this->arguments['DirectoryIndex'];
  144. if(empty($directoryIndex)) {
  145. $headers[0] = 'HTTP/1.1 403 Forbidden';
  146. $code = '403';
  147. }else{
  148. $list = explode(' ', $directoryIndex);
  149. foreach($list as $index) {
  150. if(file_exists($file .'/'. $index)) {
  151. $file .= '/'. $index;
  152. if(file_exists($file) && is_file($file))
  153. $extension = pathinfo($file, PATHINFO_EXTENSION);
  154. $array_key_exists = array_key_exists($extension, $this->arguments['MimeTypes']);
  155. if($array_key_exists) {
  156. $mime_types = $this->arguments['MimeTypes'][$extension];
  157. }else{
  158. $this->otect_stream = true;
  159. $headers[3] = sprintf('Content-Type: application/octet-stream');
  160. array_push($headers, 'Accept-Ranges: bytes');
  161. array_push($headers, 'Accept-Length: '.filesize($local_request_file));
  162. array_push($headers, 'Content-Disposition: attachment; filename='.basename($local_request_file));
  163. }
  164. $find = true;
  165. break;
  166. }
  167. }
  168. }
  169. if(!$find) {
  170. $html = $this->error_page('403', $this->arguments['ServerTokens']);
  171. }else{
  172. if(!$this->octet_stream)
  173. $headers[3] = sprintf('Content-Type: %s; charset=%s', $mime_types, 'utf-8');
  174. $html = $this->get_local_handle_buffer($file);
  175. }
  176. return -1;
  177. }else{
  178. $html = $this->get_local_handle_buffer($file);
  179. }
  180. return 1;
  181. }
  182. public function get_local_handle_buffer($file) {
  183. $handle = fopen($file, 'rb');
  184. return $this->get_buffer($handle);
  185. }
  186. public function get_buffer($handle) {
  187. $buffer = '';
  188. if(!is_resource($handle)) return null;
  189. while(!feof($handle))
  190. $buffer .= fgets($handle, 1024);
  191. fclose($handle);
  192. return $buffer;
  193. }
  194. }
  195. function gmtdate() {
  196. return (string) date('D, d M Y H:i:s'). ' GMT';
  197. }
  198. function logs($string, $perfix = true) {
  199. ob_start();
  200. echo $perfix ?
  201. sprintf("[ %s ] %s\n", date('d-M-Y H:i:s'), $string) :
  202. sprintf("\0\0[ %s ]\n", $string);
  203. ob_end_flush();
  204. }
  205. $mime_types = array(
  206. 'htm'=> 'text/html',
  207. 'html'=> 'text/html',
  208. 'jpg'=> 'image/jpeg',
  209. 'jpeg'=> 'image/jpeg',
  210. 'png'=> 'image/png',
  211. 'js'=> 'text/javascript',
  212. 'css'=> 'text/css',
  213. 'xml'=> 'text/xml');
  214. $conf = array(
  215. 'MimeTypes'=> $mime_types,
  216. 'ServerTokens'=> 'on',
  217. 'MaxRequests'=> 100,
  218. 'Timeout'=> 15,
  219. 'Listen'=> 8080,
  220. 'DocumentRoot'=> '/home/www',
  221. 'DirectoryIndex'=> 'index.htm index.html');
  222. error_reporting(E_ALL);
  223. logs('Initializing the operating environment');
  224. sleep(1);
  225. set_time_limit(0);
  226. logs('Initializing PHP-CLI execution timeout');
  227. sleep(1);
  228. $socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
  229. logs('Initializing the socket');
  230. sleep(1);
  231. logs('Initialization bind local address any ip address');
  232. sleep(1);
  233. $int = socket_bind($socket, '0.0.0.0', $conf['Listen']);
  234. logs('Initialization bind local port '.$conf['Listen']);
  235. if(!$int){
  236. logs($conf['Listen'].' Port is occupied by other services'."\n");
  237. exit(0);
  238. }
  239. sleep(1);
  240. socket_listen($socket, 1024);
  241. logs('Opening a socket listening');
  242. sleep(1);
  243. logs('Waiting for clients to access');
  244. echo "\n";
  245. $i = 0;
  246. while(1) {
  247. $pthread[$i] = new pthread($socket, $conf);
  248. $pthread[$i]->start();
  249. $pthread[$i]->join();
  250. }
复制代码


Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Vorheriger Artikel:设计模式(适配器) Nächster Artikel:企业数据备份流程