Swoole\Coroutine\Server
是一个完全协程化的类,用于创建协程 TCP
服务器,支持 TCP 和 unixSocket 类型。
与 Server 模块不同之处:
动态创建销毁,在运行时可以动态监听端口,也可以动态关闭服务器
处理连接的过程是完全同步的,程序可以顺序处理 Connect
、Receive
、Close
事件
在 4.4 以上版本中可用
可使用 Co\Server
短名。
构造方法。
Swoole\Coroutine\Server::__construct(string $host, int $port = 0, bool $ssl = false, bool $reuse_port = false);
参数
功能:是否开启端口重用,效果和此节的配置一样
默认值:false
其它值:true
版本影响:Swoole 版本 >= v4.4.4
功能:是否开启 SSL 加密
默认值:false
其它值:true
功能:监听的端口【如果为 0 将由操作系统随机分配一个端口】
默认值:无
其它值:无
功能:监听的地址
默认值:无
其它值:无
string $host
int $port
bool $ssl
bool $reuse_port
提示
参数错误、绑定地址和端口失败、listen
失败时将抛出 Swoole\Exception
异常。
0.0.0.0/127.0.0.1
: IPv4 地址
::/::1
: IPv6 地址
unix:/tmp/test.sock
: UnixSocket 地址
$host 参数支持 3 种格式
异常
设置协议处理参数。
Swoole\Coroutine\Server->set(array $options);
配置参数
必须在 start() 方法之前设置参数
长度协议
参数 $options
必须为一维的关联索引数组,与 setprotocol 方法接受的配置项完全一致。
$server = new Swoole\Coroutine\Server('127.0.0.1', $port, $ssl); $server->set([ 'open_length_check' => true, 'package_max_length' => 1024 * 1024, 'package_length_type' => 'N', 'package_length_offset' => 0, 'package_body_offset' => 4, ]);
SSL 证书设置
$server->set([ 'ssl_cert_file' => dirname(__DIR__) . '/ssl/server.crt', 'ssl_key_file' => dirname(__DIR__) . '/ssl/server.key', ]);
Swoole\Coroutine\Server->handle(callable $fn);
参数
功能:设置连接处理函数
默认值:无
其它值:无
callable $fn
示例
$server->handle(function (Swoole\Coroutine\Server\Connection $conn) { while (true) { $data = $conn->recv(); } });
- 服务器在 Accept
(建立连接) 成功后,会自动创建协程并执行 $fn
;
-$fn
是在新的子协程空间内执行,因此在函数内无需再次创建协程;
-$fn
接受一个参数,类型为 Swoole\Coroutine\Server\Connection 对象;
- 可以使用 exportSocket() 得到当前连接的 Socket 对象
终止服务器。
底层支持 start
和 shutdown
多次调用
Swoole\Coroutine\Server->shutdown(): bool
启动服务器。
Swoole\Coroutine\Server->start(): bool
返回值
启动失败会返回 false
,并设置 errCode
属性
启动成功将进入循环,Accept
连接
Accept
(建立连接) 后会创建一个新的协程,并在协程中调用 handle 方法指定的函数
错误处理
当 Accept
(建立连接) 发生 Too many open file
错误、或者无法创建子协程时,将暂停 1
秒然后再继续 Accept
发生错误时,start()
方法将返回,错误信息将会以 Warning
的形式报出。
Swoole\Coroutine\Server\Connection
对象提供了四个方法:
接收数据,如果设置了协议处理,将每次返回完整的包
function recv(float $timeout = 0)
发送数据
function send(string $data)
关闭连接
function close(): bool
得到当前连接的 Socket 对象。可调用更多底层的方法,请参考 Swoole\Coroutine\Socket
function exportSocket(): Swoole\Coroutine\Socket
use Swoole\Process; use Swoole\Coroutine; use Swoole\Coroutine\Server\Connection; //多进程管理模块 $pool = new Process\Pool(2); //让每个OnWorkerStart回调都自动创建一个协程 $pool->set(['enable_coroutine' => true]); $pool->on('workerStart', function ($pool, $id) { //每个进程都监听9501端口 $server = new Swoole\Coroutine\Server('127.0.0.1', 9501, false, true); //收到15信号关闭服务 Process::signal(SIGTERM, function () use ($server) { $server->shutdown(); }); //接收到新的连接请求 并自动创建一个协程 $server->handle(function (Connection $conn) { while (true) { //接收数据 $data = $conn->recv(1); if ($data === '' || $data === false) { $errCode = swoole_last_error(); $errMsg = socket_strerror($errCode); echo "errCode: {$errCode}, errMsg: {$errMsg}\n"; $conn->close(); break; } //发送数据 $conn->send('hello'); Coroutine::sleep(1); } }); //开始监听端口 $server->start(); }); $pool->start();
如果在 Cygwin 环境下运行请修改为单进程。$pool = new Swoole\Process\Pool(1);