php设置accept,PHP socket_accept 用法 手册 | 示例代码

该代码示例展示了一个使用PHP编写的非阻塞式守护进程服务器,通过pcntl_fork和socket_accept实现对每个客户端连接的 fork。服务器监听指定地址和端口,接收到信号时能正确处理,包括SIGTERM、SIGINT和SIGCHLD。当有新的客户端连接时,会创建子进程来处理交互。
摘要由CSDN通过智能技术生成

If you want to make a daemon process that forks on each client connection, you'll find out that there's a bug in PHP. The child processes send SIGCHLD to their parent when they exit but the parent can't handle signals while it's waiting for socket_accept (blocking).

Here is a piece of code that makes a non-blocking forking server.

#!/usr/bin/php -q

* Listens for requests and forks on each connection

*/$__server_listening=true;error_reporting(E_ALL);set_time_limit(0);ob_implicit_flush();

declare(ticks=1);become_daemon();/* nobody/nogroup, change to your host's uid/gid of the non-priv user */change_identity(65534,65534);/* handle signals */pcntl_signal(SIGTERM,'sig_handler');pcntl_signal(SIGINT,'sig_handler');pcntl_signal(SIGCHLD,'sig_handler');/* change this to your own host / port */server_loop("127.0.0.1",1234);/**

* Change the identity to a non-priv user

*/functionchange_identity($uid,$gid)

{

if( !posix_setgid($gid) )

{

print"Unable to setgid to ".$gid."!n";

exit;

}

if( !posix_setuid($uid) )

{

print"Unable to setuid to ".$uid."!n";

exit;

}

}/**

* Creates a server socket and listens for incoming client connections

* @param string $address The address to listen on

* @param int $port The port to listen on

*/functionserver_loop($address,$port)

{

GLOBAL$__server_listening;

if(($sock=socket_create(AF_INET,SOCK_STREAM,0)) <0)

{

echo"failed to create socket: ".socket_strerror($sock)."n";

exit();

}

if(($ret=socket_bind($sock,$address,$port)) <0)

{

echo"failed to bind socket: ".socket_strerror($ret)."n";

exit();

}

if( ($ret=socket_listen($sock,0) ) <0)

{

echo"failed to listen to socket: ".socket_strerror($ret)."n";

exit();

}socket_set_nonblock($sock);

echo"waiting for clients to connectn";

while ($__server_listening)

{$connection= @socket_accept($sock);

if ($connection===false)

{usleep(100);

}elseif ($connection>0)

{handle_client($sock,$connection);

}else

{

echo"error: ".socket_strerror($connection);

die;

}

}

}/**

* Signal handler

*/functionsig_handler($sig)

{

switch($sig)

{

caseSIGTERM:

caseSIGINT:

exit();

break;

caseSIGCHLD:pcntl_waitpid(-1,$status);

break;

}

}/**

* Handle a new client connection

*/functionhandle_client($ssock,$csock)

{

GLOBAL$__server_listening;$pid=pcntl_fork();

if ($pid== -1)

{/* fork failed */echo"fork failure!n";

die;

}elseif ($pid==0)

{/* child process */$__server_listening=false;socket_close($ssock);interact($csock);socket_close($csock);

}else

{socket_close($csock);

}

}

functioninteract($socket)

{/* TALK TO YOUR CLIENT */}/**

* Become a daemon by forking and closing the parent

*/functionbecome_daemon()

{$pid=pcntl_fork();

if ($pid== -1)

{/* fork failed */echo"fork failure!n";

exit();

}elseif ($pid)

{/* close the parent */exit();

}else

{/* child becomes our daemon */posix_setsid();chdir('/');umask(0);

returnposix_getpid();

}

}?>

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值