三十五、Swoole 基础学习笔记 - Swoole 协程 Server(服务端)
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、处理连接的过程是完全同步的,程序可以顺序处理
Connect
、Receive
、Close
事件。
协程服务端案例
协程 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 对象。
我是温新,本篇文章结束。