接上
补充:
传统架构 php-fpm进程模型,是 属于预派生子进程模式
可参考fork函数,将上面的worker(单进程阻塞模型), fork出子进程,实现多客户端通信。
4.非阻塞模型
41)非阻塞模型与io多路模型
42)两个函数
(PHP 4 >= 4.3.0, PHP 5, PHP 7)
stream_set_blocking — 为资源流设置阻塞或者阻塞模式
为 stream 设置阻塞或者阻塞模。
此函数适用于支持非阻塞模式的任何资源流(常规文件,套接字资源流等)。
资源流。
mode如果 mode 为0,资源流将会被转换为非阻塞模式;如果是1,资源流将会被转换为阻塞模式。 该参数的设置将会影响到像 fgets() 和 fread() 这样的函数从资源流里读取数据。 在非阻塞模式下,调用 fgets() 总是会立即返回;而在阻塞模式下,将会一直等到从资源流里面获取到数据才能返回。
成功时返回 TRUE, 或者在失败时返回 FALSE。
——————————————————————————————————
(PHP 4> = 4.3.0,PHP 5,PHP 7)
stream_select —在给定的流数组上运行等效于select()系统调用,其超时由tv_sec和tv_usec指定
的stream_select()函数接受流的阵列,并等待他们改变状态。它的作用与socket_select()函数的作用相同,除了它作用于流上。
read将监视数组中 列出的流,以查看字符是否可用于读取(更确切地说,看是否读取不会阻塞-特别是,文件末尾的流资源也已准备就绪,在这种情况下,fread()将返回长度为零的字符串)。
writewrite将监视阵列中 列出的流,看是否不会阻塞写入。
exceptexcept将监视阵列中 列出的流,以查看是否有高优先级的异常(“带外”)数据到达。
您无需将每个数组传递给 stream_select()。您可以不使用它,而使用一个空数组NULL。同样不要忘记那些数组是通过引用传递的,并且在stream_select()返回之后将被修改 。tv_sec注意事项:
当stream_select()返回时,阵列 read,write和 except被修改,以指示哪个流资源(多个)实际改变状态。
的tv_sec和tv_usec 一起形成超时参数, tv_sec指定的秒数而 tv_usec微秒数。这timeout是stream_select()返回之前等待的时间上限。如果tv_sec和tv_usec都设置为0,stream_select()将不等待数据-而是立即返回,指示流的当前状态。
成功时,stream_select()返回修改后的数组中包含的流资源的数量,如果超时在发生任何有趣的事情之前超时,则该值为零。FALSE 返回错误并发出警告(如果系统调用被传入信号中断,则可能发生)
————————————————————————————————————————
(PHP 4, PHP 5, PHP 7)
feof — 测试文件指针是否到了文件结束的位置
测试文件指针是否到了文件结束的位。
文件指针必须是有效的,必须指向由 fopen() 或 fsockopen() 成功打开的文件(并还未由 fclose() 关闭)。
如果文件指针到了 EOF 或者出错时则返回 TRUE,否则返回一个错误(包括 socket 超时),其它情况则返回 FALSE。
431)阻塞与非阻塞对比
基类,实现类文件同上,测试服务:iostarjhy\test\Blocking\server.php同上,只是在receive事件中的放开了sleep的注释
<?php
require_once __DIR__."/../../vendor/autoload.php";
use IoStarJhy\Blocking\Worker;
$server = new Worker('0.0.0.0',9500);
$server->on('connect',function($server,$client){
dd($client,"客户端建立连接成功");
});
$server->on('receive',function(Worker $server,$client,$data){
dd($data,'处理客户端的数据');
sleep(5);
$server->send($client,'hello client');
//$server->close($client);
});
$server->on('close',function(Worker $server,$client){
dd($client,'断开连接');
//$server->close($client);
});
$server->start();
测试客户端:iostarjhy\test\Blocking\client.php
<?php
require_once __DIR__ . "/../../vendor/autoload.php";
//连接服务端
$fp = stream_socket_client("tcp://192.168.204.168:9500");
/*fwrite($fp, 'hello server');
var_dump(fread($fp, 65535));
//服务端一次只能接受到一条数据,
/*fwrite($fp, 'hello server2');
var_dump(fread($fp, 65535));
fwrite($fp, 'hello server3');
var_dump(fread($fp, 65535));*/
//阻塞 输出等待
fwrite($fp, 'hello server');
var_dump(fread($fp, 65535));
echo "<p>输出等待……返回后才输出</p>";
//设置非阻塞
/*stream_set_blocking($fp,0);
fwrite($fp, 'hello server');
fread($fp, 65535);
echo "是否在等待";*/
//应用非阻塞 --定时
/*stream_set_blocking($fp,0);
fwrite($fp, 'hello server');
fread($fp, 65535);
echo "应用定时";
while(!feof($fp)){
sleep(1);
var_dump(fread($fp, 65535));
}*/
fclose($fp);
运行,如下
由上可见,都运行完了才一下子出现收到的信息及输出信息及其它信息。
设置非阻塞部:其它文件不变,切换测试客户端注释到设置非阻塞
由上可见,客户端信息随时输出,不在等待。
设置非阻塞定时:切换测试客户端注释到设置非阻塞-定时,运行如下
由上,客户端循环且定时向服务端读取信息,直到结束
432)初识io多路复用- stream_select()
基类 iostarjhy\src\WorkerBase.php 的close方法中放开注释
public function close($client)
{
\fclose($client);
dd($client);
}
测试服务iostarjhy\test\Blocking\server.php receive事件中放开注释
$server->on('receive',function(Worker $server,$client,$data){
dd($data,'处理客户端的数据');
sleep(5);
$server->send($client,'hello client');
$server->close($client);
});
测试客户端:iostarjhy\test\Blocking\client.php
<?php
require_once __DIR__ . "/../../vendor/autoload.php";
//连接服务端
$fp = stream_socket_client("tcp://192.168.204.168:9500");
/*fwrite($fp, 'hello server');
var_dump(fread($fp, 65535));
//服务端一次只能接受到一条数据,
/*fwrite($fp, 'hello server2');
var_dump(fread($fp, 65535));
fwrite($fp, 'hello server3');
var_dump(fread($fp, 65535));*/
//阻塞 输出等待
/*fwrite($fp, 'hello server');
var_dump(fread($fp, 65535));
echo "<p>输出等待……返回后才输出</p>";*/
//设置非阻塞
/*stream_set_blocking($fp,0);
fwrite($fp, 'hello server');
fread($fp, 65535);
echo "是否在等待";*/
//应用非阻塞 --定时
/*stream_set_blocking($fp,0);
fwrite($fp, 'hello server');
fread($fp, 65535);
echo "应用定时";
while(!feof($fp)){
sleep(1);
var_dump(fread($fp, 65535));
}*/
//io多路
stream_set_blocking($fp,0);
fwrite($fp, 'hello server');
fread($fp, 65535);
echo "应用定时";
while(!feof($fp)){
sleep(1);
$read[]=$fp;
stream_select($read,$write,$error,1);
var_dump($read);
var_dump(fread($fp, 65535));
}
fclose($fp);
运行结果
说明:stream_select ()只是循环检测与服务器建立连接的 socket,依据是否有信息,简单的将其区分并归类为可读的$read及write。
注意, stream_select()只是检测并识别socket状态类型,并不读取其中的消息内容,读还是通过fread()完成!
预习:
pcntl_signal
https://php.golaravel.com/function.pcntl-signal.html
posix_kill
https://php.golaravel.com/function.posix-kill.html
pcntl_signal_dispatch
https://php.golaravel.com/function.pcntl-signal-dispatch.html
信号查询命令:kill -l
百度搜索 php实现io模型
https://blog.csdn.net/uniquenessss/article/details/107050344
相关文章:
六星教育社区-程序员编程技术分享交流学习高端论坛
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!