当前位置: 首页 > 文档资料 > Swoole 中文文档 >

Coroutine\System

优质
小牛编辑
144浏览
2023-12-01

!> 此模块文件相关不再推荐使用,相关API请使用一键协程化的方式,文件相关操作对应SWOOLE_HOOK_FILE

系统相关API的协程封装。此模块在v4.4.6正式版本后可用。大部分API基于AIO线程池实现。

!> v4.4.6以前的版本, 请使用Co短名或Swoole\Coroutine调用, 如: Co::sleepSwoole\Coroutine::sleep
v4.4.6及以后版本官方推荐使用Co\System::sleepSwoole\Coroutine\System::sleep
此修改旨在规范命名空间, 但同时也保证向下兼容 (也就是说v4.4.6版本以前的写法也是可以的, 无需修改)

方法

statvfs()

获取文件系统信息。

!> Swoole版本 >= v4.2.5 可用

Swoole\Coroutine\System::statvfs(string $path): array|false;
  • 参数

    • string $path
      • 功能:文件系统挂载的目录【如/,可以使用df和mount -l命令获取】
      • 默认值:无
      • 其它值:无
  • 使用示例

    go(function() {
        var_dump(Swoole\Coroutine\System::statvfs('/'));
    });
    
    // array(11) {
    //   ["bsize"]=>
    //   int(4096)
    //   ["frsize"]=>
    //   int(4096)
    //   ["blocks"]=>
    //   int(61068098)
    //   ["bfree"]=>
    //   int(45753580)
    //   ["bavail"]=>
    //   int(42645728)
    //   ["files"]=>
    //   int(15523840)
    //   ["ffree"]=>
    //   int(14909927)
    //   ["favail"]=>
    //   int(14909927)
    //   ["fsid"]=>
    //   int(1002377915335522995)
    //   ["flag"]=>
    //   int(4096)
    //   ["namemax"]=>
    //   int(255)
    // }

fread()

协程方式读取文件。

Swoole\Coroutine\System::fread(resource $handle, int $length = 0): string|false;

!> v4.0.4以下版本fread方法不支持非文件类型的stream,如STDINSocket,请勿使用fread操作此类资源。
v4.0.4以上版本fread方法支持了非文件类型的stream资源,底层会自动根据stream类型选择使用AIO线程池或EventLoop实现。

  • 参数

    • resource $handle

      • 功能:文件句柄【必须是fopen打开的文件类型stream资源】
      • 默认值:无
      • 其它值:无
    • int $length

      • 功能:读取的长度【默认为0,表示读取文件的全部内容】
      • 默认值0
      • 其它值:无
  • 返回值

    • 读取成功返回字符串内容,读取失败返回false
  • 使用示例

    $fp = fopen(__DIR__ . "/defer_client.php", "r");
    go(function () use ($fp)
    {
        $r = Swoole\Coroutine\System::fread($fp);
        var_dump($r);
    });

fwrite()

协程方式向文件写入数据。

Swoole\Coroutine\System::fwrite(resource $handle, string $data, int $length = 0): int|false;

!> v4.0.4以下版本fwrite方法不支持非文件类型的stream,如STDINSocket,请勿使用fwrite操作此类资源。
v4.0.4以上版本fwrite方法支持了非文件类型的stream资源,底层会自动根据stream类型选择使用AIO线程池或EventLoop实现。

  • 参数

    • resource $handle

      • 功能:文件句柄【必须是fopen打开的文件类型stream资源】
      • 默认值:无
      • 其它值:无
    • string $data

      • 功能:要写入的数据内容【可以是文本或二进制数据】
      • 默认值:无
      • 其它值:无
    • int $length

      • 功能:读取的长度【默认为0,表示写入$data的全部内容,$length必须小于$data的长度】
      • 默认值0
      • 其它值:无
  • 返回值

    • 写入成功返回数据长度,读取失败返回false
  • 使用示例

    $fp = fopen(__DIR__ . "/test.data", "a+");
    go(function () use ($fp)
    {
        $r = Swoole\Coroutine\System::fwrite($fp, "hello world\n", 5);
        var_dump($r);
    });

fgets()

协程方式按行读取文件内容。

底层使用了php_stream缓存区,默认大小为8192字节,可使用stream_set_chunk_size设置缓存区尺寸。

Swoole\Coroutine\System::fgets(resource $handle): string|false;

!> fgets函数仅可用于文件类型的stream资源,Swoole版本 >= v4.4.4 可用

  • 参数

    • resource $handle
      • 功能:文件句柄【必须是fopen打开的文件类型stream资源】
      • 默认值:无
      • 其它值:无
  • 返回值

    • 读取到EOL\r\n)将返回一行数据,包括EOL
    • 未读取到EOL,但内容长度超过php_stream缓存区8192字节,将返回8192字节的数据,不包含EOL
    • 达到文件末尾EOF时,返回空字符串,可用feof判断文件是否已读完
    • 读取失败返回false,使用swoole_last_error函数获取错误码
  • 使用示例

    $fp = fopen(__DIR__ . "/defer_client.php", "r");
    go(function () use ($fp)
    {
        $r = Swoole\Coroutine\System::fgets($fp);
        var_dump($r);
    });

readFile()

协程方式读取文件。

Swoole\Coroutine\System::readFile(string $filename): string|false;
  • 参数

    • string $filename
      • 功能:文件名
      • 默认值:无
      • 其它值:无
  • 返回值

    • 读取成功返回字符串内容,读取失败返回false,可使用swoole_last_error获取错误信息
    • readFile方法没有尺寸限制,读取的内容会存放在内存中,因此读取超大文件时可能会占用过多内存
  • 使用示例

    $filename = __DIR__ . "/defer_client.php";
    go(function () use ($filename)
    {
        $r = Swoole\Coroutine\System::readFile($filename);
        var_dump($r);
    });

writeFile()

协程方式写入文件。

Swoole\Coroutine\System::writeFile(string $filename, string $fileContent, int $flags): bool;
  • 参数

    • string $filename

      • 功能:文件名【必须有可写权限,文件不存在会自动创建。打开文件失败会立即返回false
      • 默认值:无
      • 其它值:无
    • string $fileContent

      • 功能:写入到文件的内容【最大可写入4M
      • 默认值:无
      • 其它值:无
    • int $flags

      • 功能:写入的选项【默认会清空当前文件内容,可以使用FILE_APPEND表示追加到文件末尾】
      • 默认值:无
      • 其它值:无
  • 返回值

    • 写入成功返回true
    • 写入失败返回false
  • 使用示例

    $filename = __DIR__ . "/defer_client.php";
    go(function () use ($filename)
    {
        $w = Swoole\Coroutine\System::writeFile($filename, "hello swoole!");
        var_dump($w);
    });

sleep()

进入等待状态。

相当于PHPsleep函数,不同的是Coroutine::sleep协程调度器实现的,底层会yield当前协程,让出时间片,并添加一个异步定时器,当超时时间到达时重新resume当前协程,恢复运行。

使用sleep接口可以方便地实现超时等待功能。

Swoole\Coroutine\System::sleep(float $seconds): void;
  • 参数

    • float $seconds
      • 功能:睡眠的时间【必须大于0,最大不得超过一天时间(86400秒)】
      • 值单位:秒,最小精度为毫秒(0.001秒)
      • 默认值:无
      • 其它值:无
  • 使用示例

    $server = new Swoole\Http\Server("127.0.0.1", 9502);
    
    $server->on('Request', function($request, $response) {
        //等待200ms后向浏览器发送响应
        Swoole\Coroutine\System::sleep(0.2);
        $response->end("<h1>Hello Swoole!</h1>");
    });
    
    $server->start();

exec()

执行一条shell指令。底层自动进行协程调度

Swoole\Coroutine\System::exec(string $cmd): array;
  • 参数

    • string $cmd
      • 功能:要执行的shell指令
      • 默认值:无
      • 其它值:无
  • 返回值

    • 执行失败返回false,执行成功返回数组,包含了进程退出的状态码、信号、输出内容。
    array(
        'code'   => 0,  // 进程退出的状态码
        'signal' => 0,  // 信号
        'output' => '', // 输出内容
    );
  • 使用示例

    go(function() {
        $ret = Swoole\Coroutine\System::exec("md5sum ".__FILE__);
    });

gethostbyname()

将域名解析为IP。基于同步的线程池模拟实现,底层自动进行协程调度

Swoole\Coroutine\System::gethostbyname(string $domain, int $family = AF_INET, float $timeout = -1): string|false
  • 参数

    • string $domain

      • 功能:域名
      • 默认值:无
      • 其它值:无
    • int $family

      • 功能:域族【AF_INET表示返回IPv4地址,使用AF_INET6时返回IPv6地址】
      • 默认值AF_INET
      • 其它值AF_INET6
    • float $timeout

      • 功能:超时时间
      • 值单位:秒,最小精度为毫秒(0.001秒)
      • 默认值-1
      • 其它值:无
  • 返回值

    • 成功返回域名对应的IP地址,失败返回false,可使用swoole_last_error获取错误信息
    array(
        'code'   => 0,  // 进程退出的状态码
        'signal' => 0,  // 信号
        'output' => '', // 输出内容
    );
  • 扩展

    • 超时控制

      $timeout参数可以控制协程等待的超时时间,在规定的时间内未返回结果,协程会立即返回false并继续向下执行。底层实现中会将该异步任务标记为cancelgethostbyname还是会在AIO线程池中继续执行。

      可修改/etc/resolv.conf设置gethostbynamegetaddrinfo底层C函数的超时时间。具体请参考 设置 DNS 解析超时和重试

  • 使用示例

    go(function () {
        $ip = Swoole\Coroutine\System::gethostbyname("www.baidu.com", AF_INET, 0.5);
        echo $ip;
    });

getaddrinfo()

进行DNS解析,查询域名对应的IP地址。

gethostbyname不同,getaddrinfo支持更多参数设置,而且会返回多个IP结果。

Swoole\Coroutine\System::getaddrinfo(string $domain, int $family = AF_INET, int $socktype = SOCK_STREAM, int $protocol = STREAM_IPPROTO_TCP, string $service = null, float $timeout = -1): array|false
  • 参数

    • string $domain

      • 功能:域名
      • 默认值:无
      • 其它值:无
    • int $family

      • 功能:域族【AF_INET表示返回IPv4地址,使用AF_INET6时返回IPv6地址】
      • 默认值:无
      • 其它值:无

      !> 其他参数设置请参考man getaddrinfo文档

    • int $socktype

      • 功能:协议类型
      • 默认值SOCK_STREAM
      • 其它值SOCK_DGRAMSOCK_RAW
    • int $protocol

      • 功能:协议
      • 默认值STREAM_IPPROTO_TCP
      • 其它值STREAM_IPPROTO_UDPSTREAM_IPPROTO_STCPSTREAM_IPPROTO_TIPC0
    • string $service

      • 功能
      • 默认值:无
      • 其它值:无
    • float $timeout

      • 功能:超时时间
      • 值单位:秒,最小精度为毫秒(0.001秒)
      • 默认值-1
      • 其它值:无
  • 返回值

    • 成功返回多个IP地址组成的数组,失败返回false
  • 使用示例

    go(function () {
        $ips = Swoole\Coroutine\System::getaddrinfo("www.baidu.com");
        var_dump($ips);
    });

dnsLookup()

域名地址查询。

Coroutine\System::gethostbyname不同,Coroutine\System::dnsLookup是直接基于UDP客户端网络通信实现的,而不是使用libc提供的gethostbyname函数。

!> Swoole版本 >= v4.4.3 可用,底层会读取/etc/resolve.conf获取DNS服务器地址,目前仅支持AF_INET(IPv4)域名解析。

Swoole\Coroutine\System::dnsLookup(string $domain, float $timeout = 5): string|false
  • 参数

    • string $domain

      • 功能:域名
      • 默认值:无
      • 其它值:无
    • float $timeout

      • 功能:超时时间
      • 值单位:秒,最小精度为毫秒(0.001秒)
      • 默认值5
      • 其它值:无
  • 返回值

    • 解析成功返回对应的IP地址
    • 失败返回false,可以使用swoole_last_error获取错误信息
  • 常见错误

    • SWOOLE_ERROR_DNSLOOKUP_RESOLVE_FAILED:此域名无法解析,查询失败
    • SWOOLE_ERROR_DNSLOOKUP_RESOLVE_TIMEOUT:解析超时,DNS服务器可能存在故障,无法在规定的时间内返回结果
  • 使用示例

    go(function () {
        $ip = Swoole\Coroutine\System::dnsLookup("www.baidu.com");
        echo $ip;
    });