引言

本文基于原生的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才会返回。可以看到是阻塞的两个部分。

  1. CPU把数据从磁盘读到内核缓冲区。
  2. 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的完成。

image-20210401232838397