🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
## **Swoole概述** [Swoole](https://www.swoole.com/)是面向生产环境的PHP异步网络通信引擎,使用纯C语言编写(Swoole 4 开始逐渐改为通过 C++ 编写),提供了PHP语言的异步多线程服务器、异步TCP/UDP网络客户端、异步MySQL、异步Redis、数据连接池、AsyncTask、消息队列、毫秒定时器、异步文件读写、异步DNS查询。除了异步IO的支持外,Swoole还为PHP多进程的模式设计了多个并发数据结构和IPC通信机制,可以大大简化多进程并发编程的工作。 之前PHP一直被诟病的一个原因就是它是同步阻塞式语言,这在Web应用这种IO密集型领域,对于编写高并发高性能的应用是一个重大阻碍。有了[Swoole]([https://wiki.swoole.com](https://wiki.swoole.com/))之后,PHP开发人员可以轻松编写高性能的异步并发TCP、UDP、Unix Socket、HTTP以及WebSocket服务,从而使得PHP语言在异步IO和网络通信领域开疆拓土。 ## **安装启用** Swoole是PHP的一个扩展,可以通过PHP扩展的方式进行安装和启用(不同于普通的扩展只是提供一个库函数,`Swoole`扩展在运行后会接管`PHP`的控制权,进入事件循环,当`IO`事件发生后底层会自动回调指定的`PHP`函数)。 如果是在服务器安装的话,以Ubuntu系统为例,通过执行下列命令安装即可: ``` pecl install swoole ``` 然后通过`php -i | grep php.ini`定位`php.ini`文件所在位置,并打开该配置文件,在文件末尾追加如下内容: ~~~ [swoole] extension=swoole.so ~~~ 保存并退出,在终端运行`php -m`,如果看到扩展里包含`swoole`,说明安装启用成功。 ## **测试Swoole** 下面我们基于Swoole编写两个简单的功能来测试Swoole是否可以正常工作。 ### **HTTP 服务器** 首先我们通过Swoole编写一个简单的HTTP服务器,在测试目录下创建一个`http_server.php`文件,编写文件代码如下: ``` <?php // 表明服务器启动后监听本地 9051 端口 $server = new swoole_http_server('127.0.0.1', 9501); // 服务器启动时返回响应 $server->on("start", function ($server) { echo "Swoole http server is started at http://127.0.0.1:9501\n"; }); // 向服务器发送请求时返回响应 // 可以获取请求参数,也可以设置响应头和响应内容 $server->on("request", function ($request, $response) { $response->header("Content-Type", "text/plain"); $response->end("Hello World\n"); }); // 启动 HTTP 服务器 $server->start(); ``` 这样,一个最基本的 HTTP 服务器就完成了,其工作原理和工业级的 Apache 和 Nginx 服务器类似,只不过提供的是最简单的服务器监听和响应功能罢了,我们在终端启用这个服务器: ![](https://img.kancloud.cn/ab/8f/ab8f1796dc25a583c353f7dc3298de9f_1182x94.jpg) 这样,表示服务器已经启动并且在监听请求了,到浏览器中访问`http://127.0.0.1:9501`,即可获取服务器输出响应内容: ![](https://img.kancloud.cn/8b/27/8b2710000cd240a5eaac9c8f6956fb3b_968x340.jpg) ### **TCP服务器和客户端** 接下来,我们通过Swoole及其协程特性实现一个简单的TCP服务器和客户端(TCP 协议需要双方通过三次握手建立连接后才能进行通信),我们还是在前面的测试目录下创建一个`tcp_server.php`文件用于编写 TCP 服务端代码: ``` <?php namespace Swoole; // 监听本地 9503 端口,等待客户端请求 $server = new Server("127.0.0.1", 9503); // 建立连接时输出 $server->on('connect', function ($serv, $fd){ echo "Client:Connect.\n"; }); // 接收消息时返回内容 $server->on('receive', function ($serv, $fd, $from_id, $data) { $serv->send($fd, 'Swoole: '.$data); $serv->close($fd); }); // 连接关闭时输出 $server->on('close', function ($serv, $fd) { echo "Client: Close.\n"; }); // 启动 TCP 服务器 $server->start(); ``` 然后在该目录下创建一个`tcp_client.php`文件用于编写 TCP 客户端代码: ``` <?php namespace Swoole; // Swoole4以后通过协程来实现异步通信 go(function () { $client = new Coroutine\Client(SWOOLE_SOCK_TCP); // 尝试与指定 TCP 服务端建立连接(IP和端口号需要与服务端保持一致,超时时间为0.5秒) if ($client->connect("127.0.0.1", 9503, 0.5)) { // 建立连接后发送内容 $client->send("hello world\n"); // 打印接收到的消息 echo $client->recv(); // 关闭连接 $client->close(); } else { echo "connect failed."; } }); ``` 这样,一个最基本的 TCP 服务端和客户端程序就编写完成了,在终端先启动 TCP 服务端: ~~~ php tcp_server.php ~~~ 然后新开启一个终端窗口,启动 TCP 客户端,可以看到输出从 TCP 服务端接收到消息后 TCP 客户端退出,此时服务端也会打印连接建立和断开的日志消息: ![](https://img.kancloud.cn/8d/27/8d27d00d62c2c59a1c53a4fb29210c6b_1066x122.jpg) 客户端退出后,服务端依然处理监听状态,等待下一个请求。 >注:进程是应用程序的启动实例,拥有代码和打开的文件资源,数据资源,独立的内存空间; 线程是程序的执行者,一个进程至少包含一个主线程,也可有更多的子线程,线程有分时调度,抢占式调度两种调度策略; 协程是轻量级线程,它的创建、切换、挂起、销毁全为内存操作,消耗非常低。协程在线程里执行,由用户手动切换调度【用户空间线程】,其调度策略是协作式调度。目前Swoole4仅有部分事件回调函数底层自动创建了协程,以下回调函数可以调用协程客户端,可以查看这里https://wiki.swoole.com/wiki/page/696.html;