本文主要讲述在 Ubuntu 下编译安装 Swoole,并根据官方文档给出的demo进行了测试和搬运,包括:TCP服务器、UDP服务器、HTTP服务器、WebSocket服务器、异步客户端、定时器和协程相关,通过模仿官方例子领略Swoole给PHPer带来全新的编程模式和思想。 它弥补PHP在网络编程的不足。 一、说明 运行环境:win10 下的 Ubuntu、PHP7.2、Swoole4.3 参考文档: https://wiki.swoole.com/wiki/page/p-quickstart.html 二、安装Swoole 下载解压 sudo wget https://github.com/swoole/swoole-src/archive/v4.3.6.tar.gz cp v4.3.6.tar.gz swoole-v4.3.6.tar.gz tar -zxvf swoole-v4.3.6.tar.gz cd swoole-v4.3.6 安装依赖 # 根据下面的编译提示进行选择安装 sudo apt-get install php-dev sudo apt-get install autoconf 编译安装 # 根据自己 php 安装的目录 cd swoole-v4.3.6 /usr/local/php/bin/phpize ./configure make sudo make install make 的结果: ... ---------------------------------------------------------------------- Libraries have been installed in: /home/fly/swoole-src-4.3.6/modules If you ever happen to want to link against installed libraries in a given directory, LIBDIR, you must either use libtool, and specify the full pathname of the library, or use the `-LLIBDIR' flag during linking and do at least one of the following: - add LIBDIR to the `LD_LIBRARY_PATH' environment variable during execution - add LIBDIR to the `LD_RUN_PATH' environment variable during linking - use the `-Wl,--rpath -Wl,LIBDIR' linker flag - have your system administrator add LIBDIR to `/etc/ld.so.conf' See any operating system documentation about shared libraries for more information, such as the ld(1) and ld.so(8) manual pages. ---------------------------------------------------------------------- Build complete. Don't forget to run 'make test'. sudo make install 的结果: Installing shared extensions: /usr/local/php/lib/php/extensions/no-debug-non-zts-20170718/ Installing header files: /usr/local/php/include/php/ 配置 php.ini # 编译安装成功后,在 php.ini 文件加入 extension=swoole.so # extension=/usr/lib/php/20170718/swoole.so 查看是否加载 swoole 扩展 php -m 错误排查(可忽略) 下面错误很明显,需要指定 php-conf 路径: configure: error: Cannot find php-config. Please use --with-php-config=PATH 解决方法: ./configure --with-php-config=/usr/local/php/bin/php-config 三、快速入门 a) TCP 服务器 # 创建 php 文件 vi tcp_server.php on('Connect', function ($serv, $fd) { echo "Client: Connect.\n"; }); //监听数据接收事件 $serv->on('Receive', function ($serv, $fd, $from_id, $data) { $serv->send($fd, "Server: ".$data); }); //监听连接关闭事件 $serv->on('Close', function ($serv, $fd) { echo "Client: Close.\n"; }); //启动服务器 $serv->start(); # 程序运行测试 # 运行 server php tcp_server.php # 使用telnet 测试(退出telnet:Ctrl+] 回车,输入quit 回车) telnet 127.0.0.1 9501 b) UDP 服务器 vi udp_server.php on('Packet', function ($serv, $data, $clientInfo) { $serv->sendto($clientInfo['address'], $clientInfo['port'], "Server ".$data); var_dump($clientInfo); }); //启动服务器 $serv->start(); # 运行 php udp_server.php # 使用 netcat 连接 netcat -u 127.0.0.1 9502 c) HTTP 服务器 vi http_server.php on('request', function ($request, $response) { if ($request->server['path_info'] == '/favicon.ico' || $request->server['request_uri'] == '/favicon.ico') { return $response->end(); } var_dump($request->get, $request->post); $response->header("Content-Type", "text/html; charset=utf-8"); $response->end("

Hello Swoole. #".rand(1000, 9999)."

"); }); $http->start(); # 程序运行测试 php http_server.php # 浏览器访问 127.0.0.1:9501 d) WebSocket 服务器 WebSocket服务器是建立在Http服务器之上的长连接服务器,客户端首先会发送一个Http的请求与服务器进行握手。握手成功后会触发onOpen事件,表示连接已就绪,onOpen函数中可以得到$request对象,包含了Http握手的相关信息,如GET参数、Cookie、Http头信息等。 建立连接后客户端与服务器端就可以双向通信了。 vi ws_server.php on('open', function ($ws, $request) { var_dump($request->fd, $request->get, $request->server); $ws->push($request->fd, "hello, welcome\n"); }); //监听WebSocket消息事件 $ws->on('message', function ($ws, $frame) { echo "Message: {$frame->data}\n"; $ws->push($frame->fd, "server: {$frame->data}"); }); //监听WebSocket连接关闭事件 $ws->on('close', function ($ws, $fd) { echo "client-{$fd} is closed\n"; }); $ws->start(); # 程序运行 php ws_server.php //使用浏览器JS代码如下 var wsServer = 'ws://127.0.0.1:9502'; var websocket = new WebSocket(wsServer); websocket.onopen = function (evt) { console.log("Connected to WebSocket server."); }; websocket.onclose = function (evt) { console.log("Disconnected"); }; websocket.onmessage = function (evt) { console.log('Retrieved data from server: ' + evt.data); }; websocket.onerror = function (evt, e) { console.log('Error occured: ' + evt.data); }; e) 定时器 swoole提供了类似JavaScript的setInterval/setTimeout异步高精度定时器,粒度为毫秒级。 vi timer_tick.php //每隔2000ms触发一次 $timerId = swoole_timer_tick(2000, function ($timer_id) { echo "tick-2000ms\n"; }); //9000ms后执行此函数 swoole_timer_after(9000, function () use ($timerId) { echo "after-9000ms.\n"; //清除定时器 swoole_timer_clear($timerId); }); php timer_tick.php f) 同步、异步 TCP 客户端 vi tcp_client.php connect('127.0.0.1', 9501, 0.5)) { die("connect failed."); } //向服务器发送数据 if (!$client->send("hello world")) { die("send failed."); } //从服务器接收数据 $data = $client->recv(); if (!$data) { die("recv failed."); } echo $data; //关闭连接 $client->close(); # 异步只能用于cli vi tcp_async_client.php on("connect", function($cli) { $cli->send("hello world\n"); }); //注册数据接收回调 $client->on("receive", function($cli, $data){ echo "Received: ".$data."\n"; }); //注册连接失败回调 $client->on("error", function($cli){ echo "Connect failed\n"; }); //注册连接关闭回调 $client->on("close", function($cli){ echo "Connection close\n"; }); //发起连接 $client->connect('127.0.0.1', 9501, 0.5); g) 协程客户端 vi xxx.php on('request', function ($request, $response) { $db = new Swoole\Coroutine\MySQL(); $db->connect([ 'host' => '127.0.0.1', 'port' => 3306, 'user' => 'user', 'password' => 'pass', 'database' => 'test', ]); $data = $db->query('select * from test_table'); $response->end(json_encode($data)); }); $http->start(); h) 协程:并发 shell_exec vi xxx.php