stream_socket_xxx函数详细介绍以及与socket_xxx函数的区别

上文说明了socket的原理和使用,衔接上文介绍一下stream_socket_xxx函数,且与socket_xxx函数的区别

目录

 一、stream_socket_xxx函数介绍

1.1 Streams的含义

1.2 PHP中stream_socket_xxx函数介绍

1.3  php实现stream_socket_xxx函数的RPC远程方法调用

 二、socket_xxx函数与stream_socket_xxx函数的区别


 一、stream_socket_xxx函数介绍

1.1 Streams的含义

流(Streams)它用于统一文件、网络、数据压缩等类文件操作方式,并为这些类文件操作提供一组通用的函数接口。在最简单的定义中,一个stream就是一个具有流式行为的资源对象。也就是说,它可以线性方式对stream进行读取或写入,并且可以用fseek()跳转到stream内的任意位置

流有点类似数据库抽象层,在数据库抽象层方面,不管使用何种数据库,在抽象层之上都使用相同的方式操作数据,
而流是对数据的抽象,它不管是本地文件还是远程文件还是压缩文件等等,只要来的是流式数据(是一组顺序、大量、快速、连续到达的数据序列,像流水一样来一点数据,处理一点,流式数据被封装成了byte流(其实也是二进制的)如果是全部收到数据以后再处理,那么延迟会很大,而且在很多场合会消耗大量内存),那么操作方式就是一样的
有了流这个概念就引申出了包装器wrapper这个概念
每一种流都实现了一个包装器(wrapper)类【即Stream 可以通过 <scheme>://<target> 方式来引用。其中<scheme>是包装类的名字,<target>中的内容是由包装类的语法指定,不同的包装类的语法会有所不同。】,包装器类包含一些额外的代码用来处理特殊的协议编码。PHP提供了一些内置的包装器类,我们也可以很轻松的创建和注册自定义的包装器类。我们甚至容可以使用上下文(contexts)和过滤器来改变和增强包装器

PHP默认的包装类是file://,也就是说我们在访问文件系统的时候,其实就是在使用一个stream。我们可以通过下面两种方式来读取文件中的内容,readfile('/path/to/somefile.txt')或者readfile('file:///path/to/somefile.txt'),这两种方式是等效的。如果你是使用readfile('http://google.com/'),那么PHP会选取HTTP stream包装类来进行操作。

1.2 PHP中stream_socket_xxx的函数介绍

stream_socket_xxx常用函数:

stream_socket_client() - 打开Internet或Unix域套接字连接
stream_socket_server() -创建Internet或Unix域服务器套接字
stream_socket_accept — 接受由 stream_socket_server() 创建的套接字连接
stream_set_blocking() - 为资源流设置阻塞或者阻塞模式
stream_set_timeout() - 设置流的超时时间
stream_select() - 在tv_sec和tv_usec指定的超时时间内,对给定的流数组运行等效的select()系统调用
fgets() - 从文件指针中读取一行
fgetss() - 从文件指针中读取一行并过滤掉 HTML 标记
fwrite() - 写入文件(可安全用于二进制文件)
fread() - 读取文件(可安全用于二进制文件)
fclose() - 关闭一个已打开的文件指针
feof() - 测试文件指针是否到了文件结束的位置

1.3  php实现stream_socket_xxx函数的RPC远程方法调用

创建服务端代码 rpc_server.php

<?php

/*
* 服务端
*/

class RpcServer{

    private $port = 0; // 监听端口号
    private $host = ''; // IP

    public function __construct($host, $port){
        $this->host = $host;
        $this->port = $port;
    }

    /**
     * 运行, 监听端口并处理
     */
    public function run(){
        // 创建socket
        $server = stream_socket_server("tcp://{$this->host}:{$this->port}");
        if(empty($server)) throw new Exception('创建套接字失败');
        // 监听
        while (true){
            $client = stream_socket_accept($server);
            if(empty($client)) continue;
            // 处理请求
            $this->disposeClient($client);
            fclose($client);
        }
    }

    private function disposeClient($client){
        $buf = fread($client, 4096);
        $array = json_decode($buf, true);
        // 创建对象并调用方法
        $class = $array['class'] ?? '';
        $method = $array['method'] ?? '';
        $params = $array['params'] ?? [];
        $instance = new $class();
        $result = $instance->$method(...$params);
        fwrite($client, json_encode($result));
    }
}
// 测试调用类
class Test{
    public function returnFunction(){
        return 'connect_success';
    }

    public function add($a, $b){
        return $a + $b;
    }
}

(new RpcServer('127.0.0.1', 8888))
    ->run();

创建客户端代码 rpc_client.php

<?php

/*
* 客户端
*/

class RpcClient{
    private $urlInfo = null;
    private $className = '';

    private function __construct($url, $className){
        $this->urlInfo = parse_url($url);
        $this->className = $className;
    }

    public static function getInstance($className){
        return new RpcClient('127.0.0.1:8888', $className);
    }

    public function __call($name, $arguments){
        // 创建客户端
        $client = stream_socket_client("tcp://{$this->urlInfo['host']}:{$this->urlInfo['port']}");
        if(empty($client)) return null;
        // 发送数据
        fwrite($client, json_encode([
            'class' => $this->className,
            'method' => $name,
            'params' => $arguments,
        ]));
        // 接收返回
        $data = fread($client, 4096);
        // 关闭客户端
        fclose($client);
        return json_decode($data, true);
    }
}

$test = RpcClient::getInstance('Test');
echo $test->returnFunction();
echo PHP_EOL;
echo $test->add(2, 6);
echo PHP_EOL;

执行结果:

 二、socket_xxx函数与stream_socket_xxx函数的区别

通过对比上篇文章socket_xxx函数的使用和stream_socket_xxx函数可以发现,stream_socket_xxx函数建立客户端或者服务的只需要一个函数即可,而socket_xxx函数需要执行几次函数,相对来说stream_socket_xxx函数是php自带的接口,所以更好用一些,而socket_xxx函数有点类似于C语言,更底层,所以用起来复杂一些。

1、socket_xxx函数需要安装扩展,stream_socket_xxx函数不需要安装扩展

2、socket_xxx函数可以比stream_socket_xxx函数设置的更精确

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

m0_68949064

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值