五、Swoole 基础学习笔记 - 深入学习 Tcp Server

作者: 温新

分类: 【Swoole 系列】

阅读: 1660

时间: 2023-02-01 13:43:19

hi,我是温新,一名PHPer

文章基于 Swoole 5.0 版本编写。

**学习目标:学习 Swoole Tcp Server **

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

在 Swoole 基础学习笔记 - 先把 Swoole 跑起来 篇章中,使用 Tcp 案例进行了一个简单的演示,本篇文章将对 Swoole Tcp 进行一个基础的学习,了解更多 Tcp 相关属性、方法、事件。关于回调函数参数问题,本篇文章不进行过多说明,详情请参考官方文档。

学习 Swoole/Server

如何启动一个 Server 服务

Swoole 中,如何创建一个 Server 服务?如下几步走:

  • 1、实例化 Server 对象;
  • 2、设置运行时参数(可选);
  • 3、注册回调事件('Connect、Receive、Close');
  • 4、启动 Server 服务

现在,动手实现一个 Server,代码如 下:

<?php
// 3-swoole-tcp.php

// 实例 Server 对象,监听 0.0.0.0:9501
$server = new Swoole\Server('0.0.0.0', 9501, SWOOLE_PROCESS, SWOOLE_SOCK_TCP);

// 设置参数
$server->set([
    // 设置 worker 进程数量
    'worker_num' => 2,
    // 设置 reactor 线程数量
    'reactor_num' => 3,
]);

// 监听客户端连接事件。客户端连接进来时触发
$server->on('Connect', function ($server, $fd, $reactorId) {
        echo '有人连接进来了,是一个编号为 ' . $reactorId . ' 守卫把一个身份证号为 ' . $fd . ' 的家伙放进来了' . PHP_EOL;
});

// 监听数据接收事件。服务端收到客户端数据后,在 worker 进程中出发该回调
$server->on('Receive', function ($server, $fd, $fromId, $data) {
    // 服务端收到消息后,通过 send 方法给客户端发送消息
    $server->send($fd, 'Server:' . $fd . ' ,一起去看海啊');
});

// 监听连接关闭事件。客户端关闭,或服务端主动关闭
$server->on('Close', function ($server, $fd) {
    echo '上班了,好好干';
});

// 启动服务器
$server->start();

已经有了详细的案例,那么下一步该如何操作相信大家都已经明白了。运行-测试 跑起来,这就是自己的事了。

现在开始对 Server 进行逐一分析:

1、实例化 Server 对象

创建一个 Server,只需要将其对象进行实例化操作,并指定需要绑定的 IP 地址及需要监听的 Port。若 IP 为 127.0.0.1,表示客户端只能是 本机 连接,其他客户端无法连接;若 IP 为 0.0.0.0,表示所有的客户端都能连接。

// 实例 Server 对象,监听 0.0.0.0:9501
$server = new Swoole\Server('0.0.0.0', 9501, SWOOLE_PROCESS, SWOOLE_SOCK_TCP);

2、设置运行时参数

在 Server 启动之前,可以对 Server 进行一些参数配置,如设置进程数量、线程数量、设置 worker 进程最大任务数等配置。如使用 PHP Cli 模式启动 Server 服务后,我们会看到服务一直被挂起,好像被阻塞了一样,不能做其他操作,当设置 daemonize 进行后台运行。

$server->set([
    // 设置 worker 进程数量
    'worker_num' => 2,
    // 设置 reactor 线程数量
    'reactor_num' => 3,
    // 后台守护进行运行
    // 'daemonize' => true,
]);

如何设置 worker_num 数量?官方建议设置为 CPU 核数的 1~4 倍。进程并不是开的越多越好,若设置不合理可能会适得其反。进程开的越多,占用的内存也就越多,而进程切换也就需要消耗更多的资源。worker_num 默认为 CPU 核数。

  • 启动成功后会创建 worker_num+2 个进程。Master 进程 +Manager 进程 +serv->worker_numWorker 进程。

根据现在的设置,来算算开启了多少个进程。答案是 4 个进程,你算对了吗?

3、注册事件回调函数

Swoole/Server 是事件驱动,我们只管使用而不用去关心底层是怎么实现的,当相对应的事件触发后,我们要做的是在回调函数中进行业务逻辑处理即可。

举一个例子,刷脸进门。我们只需要将脸部送进摄像头识别区域内,等待摄像头识别人脸处理,识别成功,门就开了,我们也就可以进去了。在这个过程我们几乎什么也没有做,只是把脸准了摄像头,然后门就开了。

对于我们自己创建的 Server 服务,也是一样的道理。启动一个 Server,客户端连接后触发回调函数,这个过程中,服务端不需要知道它是怎么连接进来的,总之它来了,来了,我们就可以处理,而处理就是在回调中。

// 监听客户端连接事件。客户端连接进来时触发
$server->on('Connect', function ($server, $fd, $reactorId) {
        echo '有人连接进来了,是一个编号为 ' . $reactorId . ' 守卫把一个身份证号为 ' . $fd . ' 的家伙放进来了' . PHP_EOL;
});

需要注意的是,参数 $fd 是客户端的唯一标识(当做是身份证号),用于区分不同的客户端。该标识范围在 11~1600W 且是可以复用的整数,如现在有 3 个人连接进来了,其身份证分别为 1、2、3,现在有第四个人需要连接进来,此时刚好 2 关闭了连接,第 4 个人连接进来,它的 身份证号就是 2 了。

receive 回调,需要注意的是,参数 $data 是服务端接收到的数据,这个数据是 字符串二进制内容。

4、启动 Server

Swoole/Server 只能在 Cli 模式中运行,因此不要试图使用浏览器来访问它。

// 启动服务器
$server->start();

完成这 4 个步骤,一个高性能的 Server 已经运行起来了。

$ps aux | grep php
codeing    28880  0.1  0.1 261328 27672 pts/2    Sl+  23:02   0:00 php 3-swoole-tcp.php
codeing    28881  0.0  0.0 115892  8428 pts/2    S+   23:02   0:00 php 3-swoole-tcp.php
codeing    28884  0.0  0.0 118084 10928 pts/2    S+   23:02   0:00 php 3-swoole-tcp.php
codeing    28885  0.0  0.0 118084 10928 pts/2    S+   23:02   0:00 php 3-swoole-tcp.php

为了避免文章篇幅过长,本篇 TCP 文章到此结束,我是温新,我们下篇文章见。

请登录后再评论