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 进程相关不熟悉的朋友可以参考《
》一书。
注意,在这里
Unix 中的 fork,
wait,而
setsid,更多函数可以参考 PHP Manual 中的 pcntl 和 fork 模块相关内容。
检验
下面在命令行下启动这个脚本: