[关闭]
@phper 2017-01-10T10:35:06.000000Z 字数 3908 阅读 606

swoole深入学习 5. AsyncIO 异步IO

swoole


异步IO,分很多种,但凡是IO相关的都可以借助swoole来完成。

异步文件系统IO

Swoole\Async::readFile 异步读取小型文件

Swoole\Async::readFile最大可读取4M的文件,如果要读取超大文件,请使用Swoole\Async::read函数

读取文件一定要先存在,不然报错,我准备一个2.text,内容是123456.

  1. //swoole_async_readfile最大可读取4M的文件
  2. //如果要读取超大文件,请使用swoole_async_read函数
  3. Swoole\Async::readFile("./2.text", function($fileName, $content){
  4. var_dump($fileName, $content);
  5. });
  6. echo "done" .PHP_EOL;

运行下输出:

  1. $ php async_file.php
  2. done
  3. string(8) "./2.text"
  4. 123456

Swoole\Async::writeFile 异步写入少量内容到文件

Swoole\Async::writeFile最大可写入4M, 文件不存在,会自动创建,写入会从头覆盖原先的内容

  1. //文件不存在,会自动创建,最大可写入4M
  2. //会覆盖原先的内容,从头开始覆盖
  3. Swoole\Async::writeFile("./2.text", 'v', function($fileName){
  4. var_dump($fileName);
  5. });
  6. echo "done" .PHP_EOL;
  7. //再异步读一下,写入成功没?
  8. Swoole\Async::writeFile("./2.text", 'v', function($fileName){
  9. var_dump($fileName);
  10. });

运行下输出:

  1. $ php async_file.php
  2. done
  3. string(8) "./2.text"
  4. v23456

可以看到会从头写入,原先的1被v给取代了。暂时不知此从尾部写文件。

Swoole\Async::read 异步分段读取大型文件

异步读大文件,分段读取,每次只读$trunk_size个字节,不会占用太多内存。

我准备了一个1.text的文件,大概有 35k 大小。

  1. $trunk_size = 8192;
  2. $offset = 0
  3. Swoole\Async::read("./1.text", function($fileName, $content){
  4. var_dump($fileName, strlen($content));
  5. //默认是return true, 会分段,多次执行
  6. //如果 return false,则执行一次就退出.
  7. //return false;
  8. }, $trunk_size, $offset);
  9. echo "done" .PHP_EOL;

$size,读取数据的最大长度,默认为8K = 8192字节
$offset,偏移文件指针,默认为0,表示从文件头部开始读取。必须大于等于0且小于文件总长度

运行下输出:

  1. $ php async_file.php
  2. done
  3. string(8) "./1.text"
  4. int(8192)
  5. string(8) "./1.text"
  6. int(8192)
  7. string(8) "./1.text"
  8. int(8192)
  9. string(8) "./1.text"
  10. int(8192)
  11. string(8) "./1.text"
  12. int(6459)
  13. string(8) "./1.text"
  14. int(0)

会发现了执行了多次,一次一次的异步分段在读取。$size参数设定每一次读取最大的值。

Swoole\Async::write 异步分段写入大内容到文件

Swoole\Async::write是分段读写的。不需要一次性将要写的内容放到内存里,所以只占用少量内存。

我准备了一个1.text的文件,大概有 35k 大小。写入到4.text中。

  1. $content = file_get_contents('./1.text');
  2. Swoole\Async::write("./4.text", $content, -1, function($fileName){
  3. var_dump($fileName);
  4. });
  5. echo "done" .PHP_EOL;

运行下输出:

  1. $ php async_file.php
  2. done
  3. string(8) "./4.text"

Swoole\Async::dnsLookup 异步查询DNS

当DNS查询完成时,自动回调指定的callback函数。
当DNS查询失败时,比如域名不存在,回调函数传入的$ip为空

  1. Swoole\Async::dnsLookup("www.baidu.com", function($host, $ip){
  2. var_dump($host, $ip);
  3. });
  4. Swoole\Async::dnsLookup("www.esd4343.com", function($host, $ip){
  5. var_dump($host, $ip);
  6. });
  7. echo 'dns done';

执行下:

  1. $ php async.php
  2. dns done
  3. string(13) "www.baidu.com"
  4. string(13) "14.215.177.37"
  5. string(15) "www.esd4343.com"
  6. string(0) ""

异步毫秒定时器

Swoole\Timer::tick 异步毫秒定时器

设置一个间隔时钟定时器,单位是微妙。与after定时器不同的是tick定时器会持续触发,直到调用Swoole\Timer::clear清除。而且可以设置多个相同时间间隔的定时器。

  1. $tmer_id1 = Swoole\Timer::tick(1000, function($timer_id, $params = null){
  2. echo $timer_id. "timeout\n" . microtime(true);
  3. //Swoole\Timer::clear($timer_id);
  4. });
  5. //1
  6. var_dump($timer_id1);
  7. // true
  8. var_dump(Swoole\Timer::exists($timer_id1));die;

Swoole\Timer::after 异步制定的毫秒时间后执行一次

一个一次性定时器,执行完成后就会销毁,回调函数没有任何参数

  1. $tmer_id2 = Swoole\Timer::after(1000, function(){
  2. echo "timeout\n" . microtime(true);
  3. });
  4. //2
  5. var_dump($tmer_id2);
  6. // true
  7. var_dump(Swoole\Timer::exists($tmer_id2));die;

Swoole\Timer::clear 删除定时器

使用定时器ID来删除定时器,不能用于清除其他进程的定时器,只作用于当前进程。

  1. $tmer_id1 = Swoole\Timer::tick(1, function($timer_id, $params = null){
  2. echo $timer_id. "loop" . microtime(true) . PHP_EOL;
  3. global $a; $a++;
  4. //1万次后清除
  5. if ($a >= 10000) {
  6. Swoole\Timer::clear($timer_id);
  7. }
  8. });

异步MySQL客户端

异步mysql就是异步的去连接数据库。直接上代码。

  1. <?php
  2. /**
  3. * Created by PhpStorm.
  4. * User: yangyi
  5. * Date: 2017/1/5
  6. * Time: 17:52
  7. */
  8. $db = new Swoole\Mysql;
  9. //配置文件
  10. $server = array(
  11. 'host' => '127.0.0.1',
  12. 'user' => 'root',
  13. 'password' => '123456',
  14. 'database' => 'user',
  15. );
  16. //concent方法 2个参数,第一个是配置文件,第二个是一个回调函数。
  17. $db->connect($server, function ($db, $result) {
  18. //$result 连接是否成功,只有为true时才可以执行query查询
  19. //$result 为false,可以通过`connect_errno`和`connect_error`得到失败的错误码和错误信息
  20. if ($result === false) {
  21. var_dump($db->connect_errno, $db->connect_error);
  22. die;
  23. }
  24. $sql = 'select * from ap_room limit 1';
  25. //query方法就是执行sql的方法
  26. //第一个参数是sql, 第二个参数是回调函数
  27. $db->query($sql, function($db, $result) {
  28. /*
  29. * 执行失败,$result为false
  30. * error属性获得错误信息,errno属性获得错误码
  31. */
  32. if ($result === false) {
  33. var_dump($db->error, $db->errno);
  34. }
  35. /*
  36. * 执行成功
  37. * SQL为非查询语句(inset,update,delete)$result为true
  38. * affected_rows 为影响的行数,insert_id 获得
  39. */
  40. else if ($result === true ) {
  41. var_dump($db->affected_rows, $db->insert_id);
  42. }
  43. /*
  44. * 执行成功,SQL为select语句,$result为结果数组
  45. */
  46. else {
  47. var_dump($result);
  48. }
  49. //关闭mysql连接
  50. $db->close();
  51. });
  52. });
  53. echo 33;
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注