background image

    if((socket_bind($socket, $address, $port)) === FALSE)    {        echo "Bind socket failed!\n"; 
exit;    }

    if((socket_listen($socket, $max_backlog)) === FALSE)    {        echo "Listen to socket 
failed!\n";        exit;    }

    //Loop    while(TRUE)    {        if(($accept_socket = socket_accept($socket)) === FALSE) 
{            continue;        }        else        {            socket_write($accept_socket, $res_content, 
$res_len);   

            socket_close($accept_socket);        }    }}

//Run as daemon process.function run(){    if(($pid1 = pcntl_fork()) === 0)    //First child process 
{        posix_setsid(); //Set first child process as the session leader.

        if(($pid2 = pcntl_fork()) === 0)        //Second child process, which run as daemon.        { 
//Replaced with your own domain or address.            handle_http_request('www.codinglabs.org', 
9999); 

        }        else        {            //First child process exit;            exit;        }    }    else    {        //Wait 
for first child process exit;        pcntl_wait($status);    }}

//Entry point.run();

?>

这里我假设各位对

Unix 环境编程都比较了解,所以不做太多细节的解释,只梳理一下。简

单来看,这个程序主要由两个部分组成,

handle_http_request 函数负责处理 http 请求,其编

写方法与用

C 编写的 tcp server 类似:创建 socket、绑定、监听,然后通过一个循环处理每个

connect 过来的客户端,一旦 accept 到一个连接,则输出固定的文本“PHP HTTP Server”
(当然

http 头需要首先构建好),这里没有考虑多路复用和非阻塞等情况,而只是一个简

单的同步阻塞

tcp server。

run 函数负责将整个程序变为 daemon process,方法和 Unix 环境下 C 的方法很类似,通过
两次

fork,第一次 fork 后调用 setsid 将子进程 1 变为 session leader,这样就可以让子进程 2

与其祖先

detach,即使祖先进程结束了它也会继续运行(托孤给 init 进程)。相关细节我不

再赘述,对

Unix 进程相关不熟悉的朋友可以参考

Advanced

 

    Programming

 

    in

      the

      UNIX

 

  

Environment

一书。

注意,在这里

pcntl_fork  

对应

Unix 中的 fork

pcntl_wait  

对应

wait,而

posix_setsid  

对应

setsid,更多函数可以参考 PHP Manual 中的 pcntl 和 fork 模块相关内容。

检验

下面在命令行下启动这个脚本: