php利用socket扩展写一个简单的单进程并发http服务2

接着上文说

上一篇文章只是实现了其最基本的功能,由于是顺序执行的。一次只能处理一个请求,如果多个的话,肯定会有很严重的问题。这次实现了并发。每次请求有一个新的进程来处理,同时继续接受新的请求。

贴代码:

#!/usr/local/php5.3/bin/php
<?php
	//单进程并发执行	
	error_reporting(E_ALL);
	set_time_limit(0);
	ob_implicit_flush();
	date_default_timezone_set("Asia/Shanghai"); 


	$debug = true;
	
	$user='';
	$worker_processes=0;
	$listen_ip = "127.0.0.1";
	$listen_port  = 80;
	$vhosti = array();
        
        //解析配置文件
	function pare_conf_file(){
		global $user,$worker_processes,$listen_ip,$listen_port,$vhost;
		$ini_array = parse_ini_file("./http.ini", true);
		$user=$ini_array['user'];
		$worker_processes=$ini_array['worker_processes'];
		$listen_ip = $ini_array['listen_ip'];
		$listen_port = $ini_array['listen_port'];
		$vhost = $ini_array['vhost'];
	}

	pare_conf_file();

	function response_method_404(){
		$result = "";
		$result .="HTTP/1.1 404\r\n";
		$result .="Content-Length: 14\r\n";
		$result .= "Content-Type: text/html\r\n";
		$result .="\r\nserver is not \r\n";
		return $result;
	}
	
	function response_file_404(){
		$result = "";
		$result .="HTTP/1.1 404\r\n";
		$result .="Content-Length:0\r\n";
		$result .= "Content-Type: text/html\r\n";
		$result .="\r\n\r\n";
		return $result;
	}
	
	function response_file_type_404(){
		$result = "";
		$result .="HTTP/1.1 404\r\n";
		$result .="Content-Length:11\r\n";
		$result .= "Content-Type: text/html\r\n";
		$result .="\r\ntype is not\r\n";
		return $result;
	}
	
	function response_file_img($fileurl){
		$type = mime_content_type($fileurl);
		$body = file_get_contents($fileurl);
		$len = strlen($body);
		$result="";
		$result .="HTTP/1.1 200\r\n";
		$result .="Content-Length:$len\r\n";
		$result .= "Content-Type: {$type}\r\n";
		$result .="\r\n$body\r\n";
		return $result;
	}
	
	
	function response_file_js($fileurl){
		global $request;
		$body = file_get_contents($fileurl);
		$len = strlen($body);
		$date = date('D, d M Y G:i:s ').'GMT';
		clearstatcache();
		$last_modified = date('D, d M Y G:i:s ',filemtime($fileurl)).'GMT';
		$result="";

		$result .="HTTP/1.1 200\r\n";
		$result .="Cache-Control: public\r\n";
		$result .="Date:$date\r\n";
		$result .="Last-Modified:$last_modified\r\n";
		$result .="Expires:Fri, 24 Jan 2016 10:06:05 GMT\r\n";
		$result .="Content-Length:$len\r\n";
		$result .= "Content-Type: application/x-javascript\r\n";
		$result .="\r\n$body\r\n";
	
		return $result;
	}
	
	
	function response_file_html($fileurl){
		$body = file_get_contents($fileurl);
		$len = strlen($body);
		$result = "";
		$result .="HTTP/1.1 200\r\n";
		$result .="Content-Length:$len\r\n";
		$result .= "Content-Type: text/html;charset=utf-8\r\n";
		$result .="\r\n$body\r\n";
		return $result;
	}
	
	function pare_request($str){
		clearstatcache();
		global $web_root,$request;
		$arr = explode("\r\n",$str);
		foreach( $arr as $r){
			$pos = stripos($r,":");
			if ( $pos ){
				$key = trim(substr($r,0,$pos));
				$val = trim(substr($r,$pos+1));
				$request[$key] = $val;
			}

		}
		writelog(var_export($request,true));	
		$line0 = explode(" ",$arr[0]);
		if ( $line0[0] == "GET" ){
			$fileurl = $web_root.$line0[1];
			if ( file_exists($fileurl) ){
				$pathinfo = pathinfo($fileurl);
				if ( $pathinfo['extension'] == "js" ){
					$result = response_file_js($fileurl);
				}else if ( $pathinfo['extension'] == "png" || $pathinfo['extension'] == "jpg" || $pathinfo['extension'] == "gif" ){
					$result = response_file_img($fileurl);
				}else if ( $pathinfo['extension'] == "html" ){
					$result = response_file_html($fileurl);
				}else{
					$result = response_file_type_404();
				}
			}else{
				$result = response_file_404();
			}
		}else{
			$result = response_method_404();
		}
		return $result;
	}
	
	function sig_handler($signo) 
	{

	     switch ($signo) {
			 case SIGTERM:// 处理中断信号
				echo "SIGTERM\r\n";
			    exit;
			    break;
			 case SIGHUP:
			    // 处理重启信号
				echo "SIGHUP\r\n";
				exit;
			    break;
			default:
				echo "DEFAULT\r\n";
				exit;
			    // 处理所有其他信号
			}

	}


	function writelog($msg){
		global $debug;
		if ( $debug ){
			echo $msg;
		}else{
			file_put_contents('./log.txt',$msg,FILE_APPEND | LOCK_EX);
		}
	}
	
	if ( $user ){
	    $user_info = posix_getpwnam($user);
	    $uid = $user_info['uid'];
	}else{
	    $uid = posix_getuid();
	}
	posix_setuid($uid);
	
	
	if ( !$debug ){
		//产生子进程分支
		$pid = pcntl_fork();
		if ($pid == -1) {
			 writelog("could not fork\r\n");
			die("could not fork"); //pcntl_fork返回-1标明创建子进程失败
		} else if ($pid) {
			 exit(); //父进程中pcntl_fork返回创建的子进程进程号
		} else {
			 // 子进程pcntl_fork返回的时0
		}

		// 从当前终端分离
		if (posix_setsid() == -1) {
			writelog("could not detach form terminal \r\n");
			die("could not detach from terminal");
		}
		

		// 安装信号处理器
		pcntl_signal(SIGTERM, "sig_handler");
		pcntl_signal(SIGHUP, "sig_handler");

	}
	
	
	$address = '127.0.0.1';
	$port = 1215;
	$web_root = "/home/xtgxiso/phpsource/socket";
	$request = array();

	if (($sock = socket_create(AF_INET, SOCK_STREAM, SOL_TCP)) === false) {
		writelog("socket_create() failed: reason: " . socket_strerror(socket_last_error()) . "\n");
		exit;
	}
	
	if (socket_bind($sock, $address, $port) === false) {
	    writelog("socket_bind() failed: reason: " . socket_strerror(socket_last_error($sock)) . "\n");
		exit;
	}else{
		writelog('Socket ' . $address . ':' . $port . " has been opened\n");
	}
	
	if (socket_listen($sock, 5) === false) {
	    writelog("socket_listen() failed: reason: " . socket_strerror(socket_last_error($sock)) . "\n");
		exit;
	}else{
		writelog("Listening for new clients..\n");
	}
	
	$client_id = 0;

	do{
		
		if ( ($msgsock = socket_accept($sock)) === false ) {
	        writelog("socket_accept() failed: reason: " . socket_strerror(socket_last_error($sock)) . "\n");
	        break;
	    } else {
		    $client_id += 1;
			writelog(date('Y-m-d G:i:s')."--Client #" .$client_id .": Connect\n");
		}
		
		$ppid = pcntl_fork();
		if ( $ppid == 0 ){
			socket_close($sock);
			$cur_buf = '';
			sleep(5);
			do {
				if (false === ($buf = socket_read($msgsock, 2048))) {
					writelog("socket_read() failed: reason: " . socket_strerror(socket_last_error($msgsock)) . "\n");
					break;
				}
				writelog("read start:\r\n");
				writelog($buf);
				writelog("read end:\r\n\r\n");
				$talkback = pare_request($buf);
				writelog("\r\nwrite start:\r\n");
				socket_write($msgsock, $talkback, strlen($talkback));
				//writelog($talkback);
				writelog("write end:\r\n\r\n\r\n");
				break;
			} while (true);
			socket_close($msgsock);
			exit(0);
		}else if ( $ppid > 0 ){
			socket_close($msgsock);
		}

	}while(true);

	writelog("socket_close \r\n");
	socket_close($sock);

支持配置文件,格式如下:

;user
user=roo
worker_processes=2

又进步了一点点,哈哈

thanks to innovative fashion company Zara
miranda lambert weight loss San Francisco Beauty and Accessories

collarless styles and all kinds of colors
snooki weight lossA Latest Trend among Buyers
xvideos
此条目发表在 好文推荐, 网站开发 分类目录,贴了 , 标签。将固定链接加入收藏夹。

评论功能已关闭。