从0到1搭建基于swoole的websocket服务
源码安装
wget https://github.com/swoole/swoole-src/archive/v4.5.7.tar.gz tar -xzvf v4.5.7.tar.gz cd swoole-src-4.5.7 && \ phpize && \ ./configure && \ make && sudo make install
启动扩展,需要在 php.ini 中加入如下配置来启用 Swoole 扩展
extension=swoole.so
验证是否配置成功
php -m |grep swoole
如果没有可能是 php.ini 的路径不对。
可以使用 php --ini 来定位到 php.ini 的绝对路径,Loaded Configuration File 一项显示的是加载的 php.ini 文件,如果值为 none 证明根本没加载任何 php.ini 文件,需要自己创建。
websocket示例
server代码
<?php /** * 第一版本正常运行的 */ $ws = new Swoole\WebSocket\Server('0.0.0.0', 9501); //Swoole\Runtime::enableCoroutine(SWOOLE_HOOK_ALL | SWOOLE_HOOK_CURL); $ws->set(array( 'debug_mode' => 1, 'worker_num' => 1, 'max_request' => 10000, 'daemonize' => 1, //以守护进程执行 'dispatch_mode' => 2, 'task_worker_num' => 2, //task进程的数量 'max_wait_time' => 60, 'reload_async' => true, 'heartbeat_check_interval' => 60, 'heartbeat_idle_time' => 120, 'pid_file' => '/data/nginx/logs/swoole.pid', "log_file" => "/data/nginx/logs/swoole.log",//日志 "log_rotation" => SWOOLE_LOG_ROTATION_DAILY, "open_eof_check" => true,//打开EOF检测 "package_eof" => "\r\n", //设置EOF "open_cpu_affinity" => true, "stats_file" => "/data/nginx/logs/swoole.stat", // 'ssl_cert_file' => __DIR__ . '/../config/fullchain.pem', // 'ssl_key_file' => __DIR__ . '/../config/privkey.pem' )); $newprocess = new Swoole\Process(function ($process) { global $ws;//同一个ws $redis = new Swoole\Coroutine\Redis(); $redis->connect('127.0.0.1', 6379, true); $redis->auth("crs1rwoijdvl6rqd83dvN2jaF"); if ($redis->subscribe(['msg'])) // 或者使用psubscribe { while ($msg = $redis->recv()) { // msg是一个数组, 包含以下信息 // $type # 返回值的类型:显示订阅成功 // $name # 订阅的频道名字 或 来源频道名字 // $info # 目前已订阅的频道数量 或 信息内容 list($type, $name, $info) = $msg; if ($type == 'subscribe') { // 或psubscribe // 频道订阅成功消息,订阅几个频道就有几条 } else if ($type == 'unsubscribe' && $info == 0) { // 或punsubscribe break; // 收到取消订阅消息,并且剩余订阅的频道数为0,不再接收,结束循环 } else if ($type == 'message') { // 若为psubscribe,此处为pmessage // var_dump($name); // 打印来源频道名字 var_dump("pid=" . getmypid() . " msg=" . $info); // 打印消息 var_dump(count($ws->connections) . " conns"); // $conn = $ws->getClientList(); // var_dump($conn); foreach ($ws->connections as $fd) { var_dump($fd . " fd"); // 需要先判断是否是正确的websocket连接,否则有可能会push失败 if ($ws->isEstablished($fd)) { //向 WebSocket 客户端连接推送数据,长度最大不得超过 2M。 $ws->push($fd, "hello, welcome $info\n"); } else { var_dump($fd . " fd error"); } } // balabalaba.... // 处理消息 // if ($need_unsubscribe) { // 某个情况下需要退订 // $redis->unsubscribe(); // 继续recv等待退订完成 // } } } } }, false, 2, 1); $ws->addProcess($newprocess); //监听WebSocket连接打开事件 $ws->on('open', function ($ws, $request) { // $ws->connections[] = $request->fd; var_dump($request->fd); $ws->push($request->fd, "open\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"; }); //workstart事件 $ws->on('workerstart', function ($ws, $work_id) { }); //server task $ws->on('task', function ($ws, $taskid, $from_id, $data) { global $table; foreach ($table as $row) { $ws->send($row['fd'], "{$row['fd']} i am broadcast"); } $ws->finish("$data -> OK"); }); //处理异步任务的结果 $ws->on('finish', function ($ws, $task_id, $data) { echo "AsyncTask[$task_id] Finish: $data" . PHP_EOL; }); $ws->start();
client.html
<script> var wsServer = 'ws://123.207.190.86:9501'; var websocket = new WebSocket(wsServer); websocket.onopen = function (evt) { console.log("Connected to WebSocket server."); setInterval(ping, 60*1000); }; 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); }; function ping(){ console.log('ping'); websocket.send("ping"); } </script>
client.php
<?php Co\run(function () { $client = new Swoole\Coroutine\Http\Client("123.207.190.86", 9501); $ret = $client->upgrade("/"); if ($ret) { while (true) { $client->push("hello"); var_dump($client->recv()); co::sleep(1); } } });
lumen+swoole
安装 laravelS https://github.com/hhxsv5/laravel-s/blob/master/README-CN.md#%E7%89%B9%E6%80%A7
composer require "hhxsv5/laravel-s:~3.7.8" -vvv
参考
https://wiki.swoole.com/#/environment