上一篇文章只是实现了其并发功能,前一个请求的处理不会阻碍下一个请求的处理,但是是每次请求的时候产生一个新的进程,也不是很好,并且并发的效果并不好,因为只有一个进程在工作。
这次的改进是,将生成多个工作进程,提高并发性能。
贴代码:
#!/usr/local/php5.3/bin/php
//多进程--预先生成固定进程的数量来处理请求。
error_reporting(0);
set_time_limit(0);
ob_implicit_flush();
date_default_timezone_set("Asia/Shanghai");
$debug = false;
$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();
//不存在的http方法响应
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;
}
//JS类型响应
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;
}
//HTML类型响应
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;
}
//解析http请求
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 $signo."DEFAULT\r\n";
exit;
// 处理所有其他信号
}
}
//安装信号处理器
function register_sig_handler(){
pcntl_signal(SIGTERM, "sig_handler");
pcntl_signal(SIGHUP, "sig_handler");
pcntl_signal(IGCHLD, "sig_handler" );
}
//日志
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");
}
register_sig_handler();
}
$address = '127.0.0.1';
$port = 1215;
$web_root = "/home/xtgxiso/phpsource/socket";
$request = array();
$sock = false;
//创建监听socket
function listen_server_socket(){
global $sock,$address,$port;
if (($sock = socket_create(AF_INET, SOCK_STREAM, SOL_TCP)) === false) {
writelog("socket_create() failed: reason: " . socket_strerror(socket_last_error()) . "\n");
exit;
}
socket_set_nonblock($sock);
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");
}
}
listen_server_socket();
//创建工作进程
function start_work_process(){
global $sock,$client_id;
$pid = pcntl_fork();
if ( $pid == 0 ){
do{
if ( ($msgsock = socket_accept($sock)) === false ) {
writelog("socket_accept() failed: reason: " . socket_strerror(socket_last_error($sock)) . "\n");
usleep(5000);
continue;
} else {
$client_id += 1;
writelog(date('Y-m-d G:i:s')."--Client #" .$client_id .": Connect\n");
}
socket_close($sock);
$cur_buf = '';
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);
}while(true);
}else if ( $pid > 0 ){
socket_close($sock);
}
}
//创建工作进程并处理信号
$client_id = 0;
for( $i = 1; $i <= $worker_processes;$i++){
start_work_process();
}
while(1){
sleep(1);
}
writelog("socket_close \r\n");
socket_close($sock);
这样就可以提前生成比如:10个进程。一下子能力提高了10倍 。这个程序并没有将工作进程中的每个请求创建新的进程来处理(性能不太好),要是能够用线程来解决就好了。
The point of the bill is so that by 2020
christina aguilera weight loss Top 7 Formulas for Writing Articles That Get Read
negative aspects at dress for youths
miranda lambert weight lossAdvice on What to Wear at a 70s Party