PHP编写daemon process详解及实例代码
今天下午在segmentfault.com看到一个提问,提问标题是“PHP怎么做服务化”,其中问道php是不是只能以web方式调用。其实很多人对PHP的使用场景都有误解,认为php只能用于编写web脚本,实际上,从PHP4开始,php的使用场景早已不限于处理web请求。从php的架构体系来说,php分为三个层次:sapi、phpcore和zendengine。phpcore本身和web没有任何耦合,php通过sapi与其它应用程序通信,例如mod_php就是为apache编写的sapi实现,同样,fpm是一个基于fastcgi协议的sapi实现,这些sapi都是与webserver配合用于处理web请求的。但是也有许多sapi与web无关,例如clisapi可以使得在命令行环境下直接执行php,embedsapi可以将php嵌入其它语言(如Lua)那样。这里我并不打算详细讨论php的架构体系和sapi的话题,只是说明从架构体系角度目前的php早已被设计为支持各种环境,而非为web独有。除了架构体系的支持外,php丰富的扩展模块也为php在不同环境发挥作用提供了后盾,例如本文要提到的pcntl模块和posix模块配合可以实现基本的进程管理、信号处理等操作系统级别的功能,而sockets模块可以使php具有socket通信的能力。因此php完全可以用于编写类似于shell或perl常做的工具性脚本,甚至是具有server性质的daemonprocess。为了展示php如何编写daemonserver,我用php编写了一个简单的httpserver,这个server以daemonprocess的形式运行。当然,为了把重点放在如何使用php编写daemon,我没有为这个httpserver实现具体业务逻辑,但它可以监听指定端口,接受http请求并返回给客户端一条固定的文本,整个过程通过socket实现,全部由php编写而成。
代码实例
下面是这个程序的完整代码:
<?php //Accpetthehttpclientrequestandgenerateresponsecontent. //Asademo,thisfunctionjustsend"PHPHTTPServer"toclient. functionhandle_http_request($address,$port) { $max_backlog=16; $res_content="HTTP/1.1200OK Content-Length:15 Content-Type:text/plain;charset=UTF-8 PHPHTTPServer"; $res_len=strlen($res_content); //Create,bindandlistentosocket if(($socket=socket_create(AF_INET,SOCK_STREAM,SOL_TCP))===FALSE) { echo"Createsocketfailed!\n"; exit; } if((socket_bind($socket,$address,$port))===FALSE) { echo"Bindsocketfailed!\n"; exit; } if((socket_listen($socket,$max_backlog))===FALSE) { echo"Listentosocketfailed!\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); } } } //Runasdaemonprocess. functionrun() { if(($pid1=pcntl_fork())===0) //Firstchildprocess { posix_setsid();//Setfirstchildprocessasthesessionleader. if(($pid2=pcntl_fork())===0) //Secondchildprocess,whichrunasdaemon. { //Replacedwithyourowndomainoraddress. handle_http_request('www.codinglabs.org',9999); } else { //Firstchildprocessexit; exit; } } else { //Waitforfirstchildprocessexit; pcntl_wait($status); } } //Entrypoint. run(); ?>
这里我假设各位对Unix环境编程都比较了解,所以不做太多细节的解释,只梳理一下。简单来看,这个程序主要由两个部分组成,handle_http_request函数负责处理http请求,其编写方法与用C编写的tcpserver类似:创建socket、绑定、监听,然后通过一个循环处理每个connect过来的客户端,一旦accept到一个连接...
感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!