三十五、Swoole 基础学习笔记 - Swoole 协程 Server(服务端)

作者: 温新

分类: 【Swoole 系列】

阅读: 1299

时间: 2023-03-13 12:24:41

hi,我是温新,一名PHPer

文章基于 Swoole 5.0.1 版本编写。

学习目标:学习协程服务端

说明:本篇文章结合官方文档编写及参考网络资料编写,虽非全部原创,但也是结合了自己的理解,若转载请附带本文 URL,编写不易,持续编写更不易,谢谢!

Swoole\Coroutine\Server 与异步风格的服务端不同这处在于,Swoole\Coroutine\Server是完成协程化实现的服务器。

协程服务端优点:

1、不需要设置事件回调函数。建立连接、接收数据、发送数据、关闭连接都是顺序的,没有异步风格的并发问题;

2、可以动态的开启关闭服务,异步风格的服务在 start() 被调用之后就什么也干不了了,而协程风格的可以动态开启关闭服务。

协程服务端的缺点:

1、协程风格的服务不会自动创建多个进程,需要配合 Process\Pool 模块使用才能利用多核;

2、协程风格服务其实是对 Co\Socket 模块的封装,所以用协程风格的需要对 socket 编程有一定经验;

3、目前封装层级没有异步风格服务器那么高,有些东西需要自己手动实现,比如 reload 功能需要自己监听信号来做逻辑。

TCP 服务器

Swoole\Coroutine\Server 是一个完成协程化的类,用于创建协程 TCP 服务器,支持 TCP 和 unixSocket 类型。

与 Server 模块不同点:

  • 1、动态创建销毁,在运行时可以动态监听端口,也可以动态关闭服务器;
  • 2、处理连接的过程是完全同步的,程序可以顺序处理 ConnectReceiveClose 事件。

协程服务端案例

协程 TCP 服务器

<?php
// 35-swoole-coroutine-server.php

// 方式一
$scheduler = new Swoole\Coroutine\Scheduler();
$scheduler->add(function () {
    // 协程 TCP 服务端
    $server = new Swoole\Coroutine\Server('0.0.0.0', 9501);
    // 设置连接处理函数
    $server->handle(function (Swoole\Coroutine\Server\Connection $conn) {
        echo '神界:哟,来新人了:' . $conn->recv() . PHP_EOL;
        $conn->send('我是神界接引人');
    });
    $server->start();
});
$scheduler->start();


/*
// 方式二
Swoole\Coroutine\run(function () {
    $server = new Swoole\Coroutine\Server('0.0.0.0', 9501);
    $server->handle(function ($conn) {
        echo $conn->recv() . PHP_EOL;
    });
    $server->start();
});
*/

我再测试的过程中发现一个,协程服务端再接收消息时,官方手册给出了一个死循环用于接收客户端消息,如下:

$server->handle(function (Swoole\Coroutine\Server\Connection $conn) {
    while (true) {
        $data = $conn->recv();
    }
});

但我测试的实际结果是,加上 while 死循环后,服务器端会无限输出消息。方式一和方式二我都进行了测试。如果遇到问题,欢迎交流学习。

客户端

准备了两个客户端进行测试,一个异步客户端,一个协程客户端。

异步客户端

<?php
// 35-swoole-client.php

$client = new Swoole\Client(SWOOLE_SOCK_TCP);
if (!$client->connect('127.0.0.1', 9501, -1)) {
	exit('connect failed. Error:' . $client->errCode . PHP_EOL);
}
$client->send('I am Swoole Client');
echo $client->recv() . PHP_EOL;
$client->close();

协程客户端

<?php
// 35-swoole-coroutine-client.php

Swoole\Coroutine\run(function () {
    $client = new Swoole\Coroutine\Client(SWOOLE_SOCK_TCP);
    if (!$client->connect('127.0.0.1', 9501, 0.5))
    {
        echo "connect failed. Error: {$client->errCode}\n";
    }
    $client->send("hello world\n");
    echo $client->recv();
    $client->close();
});

输出结果

# 协程服务端
$php 35-swoole-coroutine-server.php 
神界:哟,来新人了:I am Swoole Client
神界:哟,来新人了:I am Swoole Client
神界:哟,来新人了:我是协程客户端
神界:哟,来新人了:我是协程客户端

# 客户端
$php 35-swoole-client.php 
我是神界接引人
$php 35-swoole-client.php 
我是神界接引人
$php 35-swoole-coroutine-client.php 
我是神界接引人
$php 35-swoole-coroutine-client.php 
我是神界接引人

协程 TCP API

__construct

含义:构造方法。

语法:

Swoole\Coroutine\Server::__construct(string $host, int $port = 0, bool $ssl = false, bool $reuse_port = false);

set

含义:设置协议处理参数。

语法:Swoole\Coroutine\Server->set(array $options);

参数:参数 $options 必须为一维的关联索引数组,与 setprotocol 方法接受的配置项完全一致。

handle

含义:设置连接处理函数。

语法:Swoole\Coroutine\Server->handle(callable $fn);

参数:$fn,设置链接处理函数。

shutdown

含义:终止服务器。

start

含义:启动服务器。

recv

含义:接收数据,如果设置了协议处理,将每次返回完整的包。

send

含义:发送数据。

close

含义:关闭连接。

exportSocket

含义:得到当前连接的 Socket 对象。

我是温新,本篇文章结束。

请登录后再评论