五大IO模型的理解及PHP简单实现

五大 I/O 模型

对于一次 IO 操作,数据会先被拷贝进操作系统内核空间的缓冲区中,然后才会从内核缓冲区中拷贝到用户空间。所以说,当一个 IO 操作发生时,它会经历两个阶段:

  1. 等待数据准备。
  2. 将数据从内核拷贝到用户空间

根据这两个阶段中用户进程等待的不同方式,可以分为以下五种 I/O 模型:

  1. 阻塞 I/O
  2. 非阻塞 I/O
  3. I/O 多路复用
  4. 信号驱动 I/O
  5. 异步 I/O

阻塞 I/O

原理介绍

在这里插入图片描述

当用户进程调用 recvfrom 系统函数,内核就开始了 IO 的第一个阶段:数据准备(对于网络 IO 来说,很多时候在一开始还没有数据的存在,内核需要在磁盘中读取数据并存放在内核中的缓冲区中)。数据准备完成后,内核会把在内核缓冲区中准备好的数据复制到用户空间的内存中。而在数据准备到数据复制到用户空间的整个过程中,用户进程一直是阻塞的。直到将数据复制到用户空间完成,内核返回成功,用户进程解除阻塞状态从而继续运行。

代码实现
  • blocking_nonblocking_io_server.php 服务端代码

    <?php
    class Worker
    {
         
      public $onConnect;
      public $onMessage;
      public function __construct($addr)
      {
         
        $this->socket = stream_socket_server($addr);
        echo "{
           $addr}服务已经启动\r\n";
      }
      public function start()
      {
         
        $this->accept();
      }
      public function accept()
      {
         
        while (true) {
         
          $client = stream_socket_accept($this->socket);
          if (is_callable($this->onConnect)) {
         
            ($this->onConnect)($this, $client);
          }
          $data = fread($client, 65535);
          if (is_callable($this->onMessage)) {
         
            ($this->onMessage)($this, $client, $data);
          }
          fclose($client);
        }
      }
      public function sentMessage($client, $data)
      {
         
        $response = "HTTP/1.1 200 OK\r\n";
        $response .= "Content-Type: text/html;charset=UTF-8\r\n";
        $response .= "Connection: keep-alive\r\n";
        $response .= "Content-length: " . strlen($data) . "\r\n\r\n";
        $response .= $data;
        fwrite($client, $response);
      }
    }
    // 调用
    $address = 'tcp://0.0.0.0:9000';
    $server = new Worker($address);
    $server->onConnect = function ($serv, $client) {
         
      // 模拟内核准备数据,延迟5秒钟
      sleep(5);
      $serv->sentMessage($client, 'hello client' . "\n");
    };
    $server->onMessage = function ($serv, $client, $data) {
         
      echo "收到來自客戶端的消息\n";
    };
    $server->start();
    
  • blocking_client.php 阻塞模型的客户端代码

    <?php
    $address = 'tcp://127.0.0.1:9000';
    // 创建客户端套接字,默认为阻塞模型
    $client = stream_socket_client($address);
    
    $time = time();
    
    fwrite($client, 'hello server');
    
    echo fread($client, 65536);
    
    echo "其他业务\r\n";
    
    $m = time() - $time;
    
    echo 
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值