page contents

swoole 第6次课-2 含毫命简:阻塞与非阻塞3

阻塞与非阻塞

接上

补充:

传统架构  php-fpm进程模型,是 属于预派生子进程模式 

attachments-2020-12-WkT2juot5fdbefe9e4410.png

可参考fork函数,将上面的worker(单进程阻塞模型), fork出子进程,实现多客户端通信。


4.非阻塞模型

41)非阻塞模型与io多路模型

attachments-2020-12-Ocbon1gS5fdbf58bc7c09.png

attachments-2020-12-XaT3aEgH5fdbf5b3a6fa4.png

42)两个函数

attachments-2020-12-3FfH07t65fdbf5c3b48ef.png

stream_set_blocking

(PHP 4 >= 4.3.0, PHP 5, PHP 7)

stream_set_blocking — 为资源流设置阻塞或者阻塞模式

说明

stream_set_blocking ( resource $stream , int $mode ) : bool

为 stream 设置阻塞或者阻塞模。

此函数适用于支持非阻塞模式的任何资源流(常规文件,套接字资源流等)。

参数

stream

资源流。

mode

如果 mode 为0,资源流将会被转换为非阻塞模式;如果是1,资源流将会被转换为阻塞模式。 该参数的设置将会影响到像 fgets() 和 fread() 这样的函数从资源流里读取数据。 在非阻塞模式下,调用 fgets() 总是会立即返回;而在阻塞模式下,将会一直等到从资源流里面获取到数据才能返回。

返回值

成功时返回 TRUE, 或者在失败时返回 FALSE

——————————————————————————————————

stream_select

(PHP 4> = 4.3.0,PHP 5,PHP 7)

stream_select —在给定的流数组上运行等效于select()系统调用,其超时由tv_sec和tv_usec指定

说明

stream_select ( array &$read , array &$write , array &$except , int $tv_sec [, int $tv_usec= 0 ]): int

stream_select()函数接受流的阵列,并等待他们改变状态。它的作用与socket_select()函数的作用相同,除了它作用于流上。

参数

read

read将监视数组中 列出的流,以查看字符是否可用于读取(更确切地说,看是否读取不会阻塞-特别是,文件末尾的流资源也已准备就绪,在这种情况下,fread()将返回长度为零的字符串)。

write

write将监视阵列中 列出的流,看是否不会阻塞写入。

except

except将监视阵列中 列出的流,以查看是否有高优先级的异常(“带外”)数据到达。

注意事项

stream_select()返回时,阵列 readwrite和 except被修改,以指示哪个流资源(多个)实际改变状态。

您无需将每个数组传递给 stream_select()您可以不使用它,而使用一个空数组NULL同样不要忘记那些数组是通过引用传递的并且在stream_select()返回之后将被修改 tv_sec

tv_sectv_usec 一起形成超时参数, tv_sec指定的秒数而 tv_usec微秒数。timeoutstream_select()返回之前等待的时间上限如果tv_sectv_usec都设置为0stream_select()将不等待数据-而是立即返回,指示流的当前状态。

返回值

成功时,stream_select()返回修改后的数组中包含的流资源的数量,如果超时在发生任何有趣的事情之前超时,则该值为零。FALSE 返回错误并发出警告(如果系统调用被传入信号中断,则可能发生)


attachments-2020-12-e6mLgCqg5fdc69616b27d.png

————————————————————————————————————————

feof

(PHP 4, PHP 5, PHP 7)

feof — 测试文件指针是否到了文件结束的位置

说明

feof ( resource $handle ) : bool

测试文件指针是否到了文件结束的位。

参数

handle

文件指针必须是有效的,必须指向由 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);

运行,如下

attachments-2020-12-gB6TywP65fdbfff5891c3.png

由上可见,都运行完了才一下子出现收到的信息及输出信息及其它信息。

设置非阻塞部:其它文件不变,切换测试客户端注释到设置非阻塞

attachments-2020-12-MIkP0ErU5fdc000bc538d.png

由上可见,客户端信息随时输出,不在等待。

设置非阻塞定时:切换测试客户端注释到设置非阻塞-定时,运行如下

attachments-2020-12-VEWQ5Y075fdc001f29c84.png

由上,客户端循环且定时向服务端读取信息,直到结束

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);

运行结果

attachments-2020-12-KeJFUvgS5fdc6bbbd1f4f.png


说明: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

相关文章:

swoole 第6次课-2 含毫命简:阻塞与非阻塞

swoole 第6次课-2 含毫命简:阻塞与非阻塞2

swoole 第6次课-2 含毫命简:阻塞与非阻塞3

六星教育社区-程序员编程技术分享交流学习高端论坛

  • 发表于 2020-12-18 07:54
  • 阅读 ( 870 )
  • 分类:swoole

你可能感兴趣的文章

相关问题

0 条评论

请先 登录 后评论
吉洪叶
吉洪叶

21 篇文章

作家榜 »

  1. 轩辕小不懂 2403 文章
  2. 小柒 1470 文章
  3. Pack 1135 文章
  4. Nen 576 文章
  5. 王昭君 209 文章
  6. 文双 71 文章
  7. 小威 64 文章
  8. Cara 36 文章