引言
本文基于原生的PHP代码实现,IO阻塞模型,所以本文章实现的阻塞模型和 swoole 没有任何关系。当然,日后用 swoole 实现该io模型肯定更加容易。但是原生php实现该模型确可以让你更好的理解这个 IO 模型。
参考文献
5种IO模型:https://blog.mailjob.net/posts/3565199751.html
github代码下载:https://github.com/mailjobblog/dev_php_io/tree/master/test/blocking
函数(stream_socket_server):https://php.golaravel.com/function.stream-socket-server.html
函数(stream_socket_client):https://php.golaravel.com/function.stream-socket-client.html
函数(fread):https://php.golaravel.com/function.fread.html
函数(fwrtie):https://php.golaravel.com/function.fwrite.html
IO阻塞模型
阻塞IO情况下,当用户调用read
后,用户线程会被阻塞,等内核数据准备好并且数据从内核缓冲区拷贝到用户态缓存区后read
才会返回。可以看到是阻塞的两个部分。
- CPU把数据从磁盘读到内核缓冲区。
- CPU把数据从内核缓冲区拷贝到用户缓冲区。
原生PHP代码演示
代码
server.php
<?php
require __DIR__."/../../vendor/autoload.php";
use DevPhpIO\Blocking\Worker;
$server = new Worker('0.0.0.0',9500);
$server->on('connect',function($server,$client){
dd($client,'连接成功');
});
$server->on('receive',function($server,$client,$data){
dd($data,'处理client的数据');
sleep(5); // 进行阻塞,方便演示
$server->send($client, "hello i’m is server");
$server->close($client);
});
$server->on('close',function($server,$client){
dd($client,'连接断开');
});
$server->start();
client.php
<?php
require __DIR__."/../../vendor/autoload.php";
$fp = stream_socket_client("tcp://127.0.0.1:9500");
fwrite($fp,'hello blocking');
var_dump(fread($fp,65535));
测试
测试后发现,两个client同时请求的时候,client2需要等待client1的完成。