1

swoole客户端

文章目录

1.swoole客户端能解决什么样的问题?

2.如何使用?

3.注意事项

1.首先明确swoole客户端能帮助我们解决什么样的问题?

业务场景当业务中需要链接TCP,UDP,socket,websocket 服务时,我们需要编写一个客户端去链接对应的服务(比如链接某些数据源)。
此时有很多种的选择,workerman的AsyncTcpConnection,或者使用php自带的socket函数(socket_create,socket_read等函数),swoole的客户端(Swoole\Client)等都可以。各有优劣,选择适合自己和业务的就好,这次我们选择Swoole\Client。

2.如何使用?

废话不多说,直接上我封装好的代码,看不懂多看注释理解,可以收藏方便以后可以直接使用。

class SwooleClient
{
    //链接对象
    private $client;

    /**
     * SwooleClient constructor.
     */
    public function __construct()
    {
        $this->client = new Swoole\Client(SWOOLE_SOCK_TCP);
        $this->client->set(array(
            'open_eof_check' => true,   //打开EOF检测
            'package_eof'    => "\r\n", //设置EOF,包之间的分隔符
            'package_max_length' => 1024 * 1024 * 2,//设置一个包的最大数据包尺寸,单位为字节。默认2m
        ));
    }

    /**
     * Notes: 链接对应的ip
     * User: 闻铃
     * DateTime: 2021/11/17 下午10:46
     * @param string $ip 链接的ip,本地或外网ip
     * @param  int $port 端口号
     * @throws \Exception
     */
    public function connect($ip = '127.0.0.1', $port = 9501)
    {
        if (!$this->client->connect($ip, $port, -1)) {
            throw new \Exception(sprintf('Swoole Error: %s', $this->client->errCode));
        }
    }

    /**
     * Notes: 发送数据
     * User: 闻铃
     * DateTime: 2021/11/17 下午10:44
     * @param $data 发送的数据
     * @return mixed
     * @throws \Exception
     */
    public function send($data)
    {
        if ($this->client->isConnected()) {
            if (!is_string($data)) {
                $data = json_encode($data);
            }
            return $this->client->send($data);
        } else {
            throw new \Exception('Swoole Server does not connected.');
        }
    }

    /**
     * Notes: 关闭链接
     * User: 闻铃
     * DateTime: 2021/11/17 下午10:45
     */
    public function close()
    {
        $this->client->close();
    }

    /**
     * Notes: 接收数据
     * User: 闻铃
     * DateTime: 2021/11/17 下午10:45
     * @return array
     */
    public function recv()
    {
        //接受数据
        return $this->client->recv();
    }
}

如果想要作为webscoket客户端的话,也是可以的,推荐使用swoole官方作者封装的websocket包(saber)(github链接:https://github.com/swlib/saber

//链接对应的websocket链接
$websocket = SaberGM::websocket('ws://127.0.0.1:9999');
while (true) {
    //接收链接推送的数据,1是接收数据的超时时间
    echo $websocket->recv(1) . "\n";

    //处理你的业务逻辑

    //给ws服务推送数据
    $websocket->push("hello");

    //协程sleep1秒
    co::sleep(1);
}

分享一个使用saber过程中遇到的实际问题
在swoole.log日志中(在swoole\server的set方法中可配置swoole运行过程中的日志信息),不熟悉的可以参考下图的配置红色标记的地方,进行日志路径的配置。
image.png

配置好日志后发现下图中出现deadlock!!!,协程死锁。
image.png

原因是,我实际项目在在where(true)中有io操作(redis读写),产生了协程切换,
因为是where(true)死循环,一直在协程切换,就出现了那个协程死锁的报错。
自己研究了半天,发现这个错误其实是不影响功能的,其实可以配置一下下图的选项,就可以屏蔽掉。
image.png

3.注意事项

使用tcp或者webscoket客户端时,一般都会伴随着心跳检测。此时调用对应的tcp链接的send方法或者saber中的psuh方法,给服务端发送对应的心跳信息即可。

本文为夜雨闻铃原创文章,转载无需和我联系,但请注明文章出处。文章出处:夜雨闻铃的思否文章(https://segmentfault.com/a/11...)


夜雨闻铃
50 声望12 粉丝

分享和记录自己成长之路遇到学习到的经验和遇到的坑(偏php和go)。为了更好更活跃的社区,尽一份自己的微薄之力。