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

上一篇文章只是实现了其并发功能,前一个请求的处理不会阻碍下一个请求的处理,但是是每次请求的时候产生一个新的进程,也不是很好,并且并发的效果并不好,因为只有一个进程在工作。

这次的改进是,将生成多个工作进程,提高并发性能。

贴代码:

#!/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

php%e5%88%a9%e7%94%a8socket%e6%89%a9%e5%b1%95%e5%86%99%e4%b8%80%e4%b8%aa%e7%ae%80%e5%8d%95%e7%9a%84%e5%a4%9a%e8%bf%9b%e7%a8%8b%e5%b9%b6%e5%8f%91http%e6%9c%8d%e5%8a%a13

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值