php cli编写一个高并发的http服务

大家都知道php的http请求处理脚本是运行在apache或php-fpm中,那么除此之外还有其他吗?有,其实php cli命令行中也是可以响应http请求并处理的,最简单的参照对象就是workman、swoole,php可以监听tcp或udp的端口,实现http协议,今天我们来试一试
<?php
$socket = stream_socket_server("0.0.0.0:8889", $errno, $errstr);
stream_set_blocking($socket, 0);//设置是否阻塞
if (!$socket) {
echo "$errstr ($errno)<br />\n";
} else {
while (true) {
$conn = @stream_socket_accept($socket);//接受客户端的请求
if ($conn)
{
fwrite($conn, '当前时间是 ' . date('n/j/Y g:i a') . "\n");//响应客户端请求
fclose($conn);
} else {
echo "no newSocket\n";
}
}
}
?>
上面面是个简单的http监听服务,具体的post、session等处理还需有更进一步的优化,好了,有的人肯定好奇,就这么几句话就实现高并发了?没那么简单,高并发还需要多个进程来进行处理,php-fpm也不止一个呀,好了,我们来写一个Worker,实现进程自我创建和管理,提高php的并发处理能力,就想餐馆,一个服务员不够就多个嘛
<?php
class Worker
{
/**
* version
* @var string
*/
const VERSION = '0.0.1';
/**
* Emitted when data is received
* @var callable
*/
public $onMessage = NULL;
/**
* 子进程的数量
* @var int
*/
public $count = 1;
/**
* Listening socket
* @var resource
*/
public $socket = NULL;
/**
* Socket name The format is like this 0.0.0.0:8000
* @var string
*/
protected $_socketName = '';
/**
* 连接socket
* @var resource
*/
protected $_connSocket = NULL;
/**
* 子进程 pid 数组
* @var array
*/
private $forkList = [];
/**
* 主进程 ID 文件
* @var string
*/
private $masterPidFile = 'master.pid';
/**
* 主进程是否停止
* @var int
*/
private $masterStop = 0;
public function __construct($socketName, $options = [])
{
$this->_socketName = $socketName;
}
public function init()
{
$this->parseCommand();
}
public function start()
{
// 判断当前程序是否已经启动
$masterPidFileExist = is_file($this->masterPidFile);
if ($masterPidFileExist) {
exit("当前程序已经在运行,请不要重启启动
");
}
// 保存主进程pid到文件用于stop,reload,status等命令操作
$masterPid = posix_getpid();
file_put_contents($this->masterPidFile, $masterPid);
pcntl_signal(SIGINT, array($this, 'signalHandler'), false);
pcntl_signal(SIGTERM, array($this, 'signalHandler'), false);
pcntl_signal(SIGUSR1, array($this, 'signalHandler'), false);
$this->listen();
// 创建count个子进程,用于接受请求和处理数据
while(count($this->forkList) < $this->count) {
$this->forkWokrer();
}
while (true)
{
//sleep(1);
pcntl_signal_dispatch(); // 信号分发
$status = 0;
$pid = pcntl_wait($status, WUNTRACED); // 堵塞直至获取子进程退出或中断信号或调用一个信号处理器,或者没有子进程时返回错误
p...点击查看剩余70%
网友评论0