Swoole 整合成一個小框架

效果

php



命令以下:

    php index.php 能夠查看到上圖

    php index.php start 開啓服務(Debug模式)

    php index.php start -d 開啓服務(Daemon模式)

    php index.php status 查看服務狀態

    php index.php reload 服務熱加載

    php index.php stop 關閉服務

index.php 這是文件名稱,你們叫什麼均可以。

目錄結構以下:

    ├─ controller    
    │     ├── ...    
    ├─ client    
    │  ├─ websocket    
    │     ├── ...    
    │  ├─ tcp    
    │     ├── ...    
    ├─ server    
    │  ├─ config    
    │     ├── config.php    
    │  ├─ core    
    │     ├── Common.php    
    │     ├── Core.php    
    │     ├── HandlerException.php    
    │  ├─ log  -- 須要 讀/寫 權限    
    │     ├── ...    
    ├─ index.php

目前就這幾個文件,後期研究新的知識點會直接集成到這裏面。

說說實現了什麼:

一、啓動了 WebSocket、HTTP、TCP、UDP 等服務。

二、WebSocket 例子,在 client/websocket 文件夾,實現了視頻彈幕。

三、HTTP 例子,在瀏覽器直接訪問:http://ip:port,邏輯代碼在 controller 文件夾。

四、TCP 例子,在 client/tcp 文件夾。

五、UDP 例子,直接運行 netcat-u ip port 便可。

六、相關配置,在 server/config 文件夾。
代碼

放不全,就放一個主要的文件吧(Core.php)。

 react

   <?php    
    if (!defined('SERVER_PATH')) exit("No Access");    
    class Core    
    {    
        private static $serv;    
        public function __construct() {    
            set_error_handler(['HandlerException', 'appError']);    
            register_shutdown_function(['HandlerException', 'fatalError']);    
        }    
        public static function run() {    
            static::checkCli();    
            static::checkExtension();    
            static::showUsageUI();    
            static::parseCommand();    
        }    
        protected static function checkCli() {    
            if (php_sapi_name() !== 'cli') {    
                exit(output('服務只能運行在 cli sapi 模式下'));    
            }    
        }    
        protected static function checkExtension() {    
            if (!extension_loaded('swoole')) {    
                exit(output('請安裝 swoole 擴展'));    
            }    
        }    
        protected static function showUsageUI() {    
            global $argc;    
            if ($argc <= 1 || $argc >3) {    
                echo PHP_EOL;    
                echo "----------------------------------------".PHP_EOL;    
                echo "|               Swoole                 |".PHP_EOL;    
                echo "|--------------------------------------|".PHP_EOL;    
                echo '|    USAGE: php index.php commond      |'.PHP_EOL;    
                echo '|--------------------------------------|'.PHP_EOL;    
                echo '|    1. start    以debug模式開啓服務   |'.PHP_EOL;    
                echo '|    2. start -d 以daemon模式開啓服務  |'.PHP_EOL;    
                echo '|    3. status   查看服務狀態          |'.PHP_EOL;    
                echo '|    4. reload   熱加載                |'.PHP_EOL;    
                echo '|    5. stop     關閉服務              |'.PHP_EOL;    
                echo "----------------------------------------".PHP_EOL;    
                echo PHP_EOL;    
                exit;    
            }    
        }    
        protected static function parseCommand() {    
            global $argv;    
            $command = $argv[1];    
            $option  = isset( $argv[2] ) ? $argv[2] : '' ;    
            switch ($command) {    
                case 'start':    
                    if ($option === '-d') { //以daemon形式啓動    
                        get_config(['set@daemonize' => true]);    
                    }    
                    self::workerStart();    
                    break;    
                case 'status':    
                    self::workerStatus();    
                    break;    
                case 'reload':    
                    self::workerReload();    
                    break;    
                case 'stop':    
                    self::workerStop();    
                    break;    
                default:    
                    echo "Bad Command.".PHP_EOL;    
            }    
        }    
        protected static function workerStart() {    
            $config = get_config();    
            self::$serv = new swoole_websocket_server($config['ip'], $config['websocket_port']);    
            self::$serv->set($config['set']);    
            self::$serv->on('Start', function ($serv) use ($config) {    
                $start = new OnStart();    
                $start::run($serv, $config);    
            });    
            self::$serv->on('ManagerStart', function ($serv) use ($config) {    
                $manager_start = new OnManagerStart();    
                $manager_start::run($serv, $config);    
            });    
            self::$serv->on('WorkerStart', function ($serv, $worker_id) use ($config) {    
                $worker_start = new OnWorkerStart();    
                $worker_start::run($serv, $worker_id, $config);    
            });    
            //TCP    
            $tcp = self::$serv->listen($config['ip'], $config['tcp_port'], SWOOLE_SOCK_TCP);    
            $tcp->set($config['tcp_set']);    
            $tcp->on('Receive', function ($serv, $fd, $reactor_id, $data) {    
                $receive = new OnReceive();    
                $receive::run($serv, $fd, $reactor_id, $data);    
            });    
            //UDP    
            $udp = self::$serv->listen($config['ip'], $config['udp_port'], SWOOLE_SOCK_UDP);    
            $udp->set($config['udp_set']);    
            $udp->on('Packet', function ($serv, $data, $client_info) {    
                $packet = new OnPacket();    
                $packet::run($serv, $data, $client_info);    
            });    
            self::$serv->on('Task', function ($serv, $task_id, $src_worker_id, $data) use ($config) {    
                $task = new OnTask();    
                $dataArr = json_decode($data, true);    
                switch ($dataArr['server']) {    
                    case "tcp":    
                        $task::tcp_task_run($serv, $task_id, $src_worker_id, $data);    
                        break;    
                    case "ws":    
                        $task::ws_task_run($serv, $task_id, $src_worker_id, $data);    
                        break;    
                }    
            });    
            self::$serv->on('Open', function ($serv, $request) {    
                echo output("onOpen: handshake success with fd={$request->fd}");    
            });    
            self::$serv->on('Message', function ($serv, $frame) {    
                $message = new OnMessage();    
                $message::run($serv, $frame);    
            });    
            self::$serv->on('Request', function ($request, $response) {    
                $req = new OnRequest();    
                $req::run($request, $response);    
            });    
            self::$serv->on('Finish', function ($serv, $task_id, $data) {    
                $finish = new OnFinish();    
                $finish::run($serv, $task_id, $data);    
            });    
            self::$serv->on('Close', function ($serv, $fd, $reactor_id){    
                try {    
                    echo output('客戶端關閉');    
                } catch(Exception $e) {    
                }    
            });    
            self::$serv->on('Shutdown', function ($serv) {    
               echo output("服務關閉");    
            });    
            self::showProcessUI();    
            self::$serv->start();    
        }    
        protected static function workerStatus() {    
            $config = get_config();    
            if (!file_exists($config['master_pid_file']) ||    
                !file_exists($config['manager_pid_file']) ||    
                !file_exists($config['worker_pid_file']) ) {    
                echo output("暫無啓動的服務");    
                return false;    
            }    
            self::showProcessUI($config);    
            $masterPidString = trim(@file_get_contents($config['master_pid_file']));    
            $masterPidArr    = explode( '-', $masterPidString);    
            echo str_pad("Master", 18, ' ', STR_PAD_BOTH ).    
                str_pad($config['master_process_name'], 26, ' ', STR_PAD_BOTH ).    
                str_pad($masterPidArr[0], 16, ' ', STR_PAD_BOTH ).    
                str_pad($masterPidArr[1], 16, ' ', STR_PAD_BOTH ).    
                str_pad($masterPidArr[2], 16, ' ', STR_PAD_BOTH ).PHP_EOL;    
            $managerPidString = trim(@file_get_contents($config['manager_pid_file']));    
            $managerPidArr    = explode( '-', $managerPidString);    
            echo str_pad("Manager", 20, ' ', STR_PAD_BOTH ).    
                str_pad($config['manager_process_name'], 24, ' ', STR_PAD_BOTH ).    
                str_pad($managerPidArr[0], 16, ' ', STR_PAD_BOTH ).    
                str_pad($managerPidArr[1], 16, ' ', STR_PAD_BOTH ).    
                str_pad($managerPidArr[2], 16, ' ', STR_PAD_BOTH ).PHP_EOL;    
            $workerPidString = rtrim(@file_get_contents($config['worker_pid_file']), '|' );    
            $workerPidArr    = explode( '|', $workerPidString );    
            if (isset($workerPidArr) && !empty($workerPidArr)) {    
                foreach ($workerPidArr as $key => $val) {    
                    $v = explode( '-', $val);    
                    echo str_pad("Worker", 18, ' ', STR_PAD_BOTH ).    
                         str_pad($config['worker_process_name'], 26, ' ', STR_PAD_BOTH ).    
                         str_pad($v[0], 16, ' ', STR_PAD_BOTH ).    
                         str_pad($v[1], 16, ' ', STR_PAD_BOTH ).    
                         str_pad($v[2], 16, ' ', STR_PAD_BOTH ).PHP_EOL;    
                }    
            }    
            $taskPidString = rtrim(@file_get_contents($config['task_pid_file']), '|' );    
            $taskPidArr  = explode( '|', $taskPidString );    
            if (isset($taskPidArr) && !empty($taskPidArr)) {    
                foreach ($taskPidArr as $key => $val) {    
                    $v = explode( '-', $val);    
                    echo str_pad("Task", 18, ' ', STR_PAD_BOTH ).    
                         str_pad($config['task_process_name'], 24, ' ', STR_PAD_BOTH ).    
                         str_pad($v[0], 20, ' ', STR_PAD_BOTH ).    
                         str_pad($v[1], 12, ' ', STR_PAD_BOTH ).    
                         str_pad($v[2], 20, ' ', STR_PAD_BOTH ).PHP_EOL;    
                }    
            }    
        }    
        protected static function workerReload() {    
            $config = get_config();    
            if (!file_exists($config['master_pid_file'])) {    
                echo output("暫無啓動的服務");    
                return false;    
            }    
            $masterPidString = trim(file_get_contents($config['master_pid_file']));    
            $masterPidArr    = explode( '-', $masterPidString);    
            if (!swoole_process::kill($masterPidArr[0], 0)) {    
                echo output("PID:{$masterPidArr[0]} 不存在");    
                return false;    
            }    
            swoole_process::kill($masterPidArr[0], SIGUSR1);    
            @unlink($config['worker_pid_file']);    
            @unlink($config['task_pid_file']);    
            echo output("熱加載成功");    
            return true;    
        }    
        protected static function workerStop() {    
            $config = get_config();    
            if (!file_exists($config['master_pid_file'])) {    
                echo output("暫無啓動的服務");    
                return false;    
            }    
            $masterPidString = trim(file_get_contents($config['master_pid_file']));    
            $masterPidArr    = explode( '-', $masterPidString);    
            if (!swoole_process::kill($masterPidArr[0], 0)) {    
                echo output("PID:{$masterPidArr[0]} 不存在");    
                return false;    
            }    
            swoole_process::kill($masterPidArr[0]);    
            $time = time();    
            while (true) {    
                usleep(2000);    
                if (!swoole_process::kill($masterPidArr[0], 0)) {    
                    unlink($config['master_pid_file']);    
                    unlink($config['manager_pid_file']);    
                    unlink($config['worker_pid_file']);    
                    unlink($config['task_pid_file']);    
                    echo output("服務關閉成功");    
                    break;    
                } else {    
                    if (time() - $time > 5) {    
                        echo output("服務關閉失敗,請重試");    
                        break;    
                    }    
                }    
            }    
            return true;    
        }    
        protected static function showProcessUI() {    
            $config = get_config();    
            if ($config['set']['daemonize'] == true) {    
                return false;    
            }    
            echo str_pad("-", 90, '-', STR_PAD_BOTH) . PHP_EOL;    
            echo "|" . str_pad("啓動/關閉", 92, ' ', STR_PAD_BOTH) . "|" . PHP_EOL;    
            echo str_pad("-", 90, '-', STR_PAD_BOTH) . PHP_EOL;    
            echo str_pad("Start success.", 50, ' ', STR_PAD_BOTH) .    
                str_pad("php index.php stop", 50, ' ', STR_PAD_BOTH) . PHP_EOL;    
            echo str_pad("-", 90, '-', STR_PAD_BOTH) . PHP_EOL;    
            echo "|" . str_pad("版本信息", 92, ' ', STR_PAD_BOTH) . "|" . PHP_EOL;    
            echo str_pad("-", 90, '-', STR_PAD_BOTH) . PHP_EOL;    
            echo str_pad("Swoole Version:" . SWOOLE_VERSION, 50, ' ', STR_PAD_BOTH) .    
                str_pad("PHP Version:" . PHP_VERSION, 50, ' ', STR_PAD_BOTH) . PHP_EOL;    
            echo str_pad("-", 90, '-', STR_PAD_BOTH) . PHP_EOL;    
            echo "|" . str_pad("IP 信息", 90, ' ', STR_PAD_BOTH) . "|" . PHP_EOL;    
            echo str_pad("-", 90, '-', STR_PAD_BOTH) . PHP_EOL;    
            echo str_pad("IP:" . $config['ip'], 50, ' ', STR_PAD_BOTH) .    
                str_pad("PORT:" . $config['websocket_port'], 50, ' ', STR_PAD_BOTH) . PHP_EOL;    
            echo str_pad("-", 90, '-', STR_PAD_BOTH) . PHP_EOL;    
            echo "|" . str_pad("進程信息", 92, ' ', STR_PAD_BOTH) . "|" . PHP_EOL;    
            echo str_pad("-", 90, '-', STR_PAD_BOTH) . PHP_EOL;    
            echo str_pad("Swoole進程", 20, ' ', STR_PAD_BOTH) .    
                str_pad('進程別名', 30, ' ', STR_PAD_BOTH) .    
                str_pad('進程ID', 18, ' ', STR_PAD_BOTH) .    
                str_pad('父進程ID', 18, ' ', STR_PAD_BOTH) .    
                str_pad('用戶', 18, ' ', STR_PAD_BOTH) . PHP_EOL;    
        }    
        protected static function signalHandler() {    
            //TODO 未完成    
            //swoole_process::signal(SIGINT, function ($signal) {    
            //    echo $signal;    
            //    return;    
            //});    
        }    
    }
相關文章
相關標籤/搜索