php使用swoole實現(xiàn)TCP服務(wù)
更新時間:2024年04月03日 08:31:09 作者:huaweichenai
這篇文章主要為大家詳細介紹了php如何使用swoole實現(xiàn)TCP服務(wù),文中的示例代碼講解詳細,具有一定的借鑒價值,有需要的小伙伴可以參考一下
這里以在Yii框架下示例
一:swoole配置TCP
'swoole' => [ // 日志文件路徑 'log_file' => '@console/log/swoole.log', // 設(shè)置swoole_server錯誤日志打印的等級,范圍是0-5。低于log_level設(shè)置的日志信息不會拋出 'log_level' => 1, // 進程的PID存儲文件 'pid_file' => '@console/log/swoole.server.pid', // HTTP協(xié)議配置 'http' => [ 'host' => '0.0.0.0', 'port' => '8889', // 異步任務(wù)的工作進程數(shù)量 'task_worker_num' => 4, ], // TCP協(xié)議配置 'tcp' => [ 'host' => '0.0.0.0', 'port' => '14000', // 異步任務(wù)的工作進程數(shù)量 'task_worker_num' => 4, // 啟用TCP-Keepalive死連接檢測 'open_tcp_keepalive' => 1, // 單位秒,連接在n秒內(nèi)沒有數(shù)據(jù)請求,將開始對此連接進行探測 'tcp_keepidle' => 5 * 60, // 探測的次數(shù),超過次數(shù)后將close此連接 'tcp_keepcount' => 3, // 探測的間隔時間,單位秒 'tcp_keepinterval' => 60, // 心跳檢測,此選項表示每隔多久輪循一次,單位為秒 'heartbeat_check_interval' => 2 * 60, // 心跳檢測,連接最大允許空閑的時間 'heartbeat_idle_time' => 5 * 60, ] ],
二:swoole實現(xiàn)TCP服務(wù)基類
<?php /** * @link http://www.u-bo.com * @copyright 南京友博網(wǎng)絡(luò)科技有限公司 * @license http://www.u-bo.com/license/ */ namespace console\swoole; use Yii; use yii\helpers\Console; use yii\helpers\ArrayHelper; /* * Swoole Server基類 * * @author wangjian * @since 0.1 */ abstract class BaseServer { /** * @var Swoole\Server */ public $swoole; /** * @var boolean DEBUG */ public $debug = false; /** * __construct */ public function __construct($httpConfig, $tcpConfig, $config = []) { $httpHost = ArrayHelper::remove($httpConfig, 'host'); $httpPort = ArrayHelper::remove($httpConfig, 'port'); $this->swoole = new \swoole_http_server($httpHost, $httpPort); $this->swoole->set(ArrayHelper::merge($config, $httpConfig)); $this->swoole->on('start', [$this, 'onStart']); $this->swoole->on('request', [$this, 'onRequest']); $this->swoole->on('WorkerStart', [$this, 'onWorkerStart']); $this->swoole->on('WorkerStop', [$this, 'onWorkerStop']); $this->swoole->on('task', [$this, 'onTask']); $this->swoole->on('finish', [$this, 'onTaskFinish']); $this->swoole->on('shutdown', [$this, 'onShutdown']); $tcpHost = ArrayHelper::remove($tcpConfig, 'host'); $tcpPort = ArrayHelper::remove($tcpConfig, 'port'); $tcpServer = $this->swoole->listen($tcpHost, $tcpPort, SWOOLE_SOCK_TCP); $tcpServer->set($tcpConfig); $tcpServer->on('connect', [$this, 'onConnect']); $tcpServer->on('receive', [$this, 'onReceive']); $tcpServer->on('close', [$this, 'onClose']); } /* * 啟動server */ public function run() { $this->swoole->start(); } /** * Server啟動在主進程的主線程時的回調(diào)事件處理 * * @param swoole_server $server */ public function onStart(\swoole_server $server) { $startedAt = $this->beforeExec(); $this->stdout("**Server Start**\n", Console::FG_GREEN); $this->stdout("master_pid: "); $this->stdout("{$server->master_pid}\n", Console::FG_BLUE); $this->onStartHandle($server); $this->afterExec($startedAt); } /** * 客戶端與服務(wù)器建立連接后的回調(diào)事件處理 * * @param swoole_server $server * @param integer $fd * @param integer $reactorId */ abstract public function onConnect(\swoole_server $server, int $fd, int $reactorId); /** * 當服務(wù)器收到來自客戶端的數(shù)據(jù)時的回調(diào)事件處理 * * @param swoole_server $server * @param integer $fd * @param integer $reactorId * @param string $data */ abstract public function onReceive(\swoole_server $server, int $fd, int $reactorId, string $data); /** * 當服務(wù)器收到來自客戶端的HTTP請求時的回調(diào)事件處理 * * @param swoole_http_request $request * @param swoole_http_response $response */ abstract public function onRequest(\swoole_http_request $request, \swoole_http_response $response); /** * Worker進程/Task進程啟動時發(fā)生 * * @param swoole_server $server * @param integer $worker_id */ abstract public function onWorkerStart(\swoole_server $server, int $worker_id); /** * Worker進程/Task進程終止時發(fā)生 * * @param swoole_server $server * @param integer $worker_id */ abstract public function onWorkerStop(\swoole_server $server, int $worker_id); /** * 異步任務(wù)處理 * * @param swoole_server $server * @param integer $taskId * @param integer $srcWorkerId * @param mixed $data */ abstract public function onTask(\swoole_server $server, int $taskId, int $srcWorkerId, mixed $data); /** * 異步任務(wù)處理完成 * * @param swoole_server $server * @param integer $taskId * @param mixed $data */ abstract public function onTaskFinish(\swoole_server $server, int $taskId, mixed $data); /** * 客戶端與服務(wù)器斷開連接后的回調(diào)事件處理 * * @param swoole_server $server * @param integer $fd */ abstract public function onClose(\swoole_server $server, $fd); /** * Server正常結(jié)束時的回調(diào)事件處理 * * @param swoole_server $server */ public function onShutdown(\swoole_server $server) { $startedAt = $this->beforeExec(); $this->stdout("**Server Stop**\n", Console::FG_GREEN); $this->stdout("master_pid: "); $this->stdout("{$server->master_pid}\n", Console::FG_BLUE); $this->onShutdownHandle($server); $this->afterExec($startedAt); } /** * Server啟動在主進程的主線程時的自定義事件處理 * * @param swoole_server $server */ protected function onStartHandle(\swoole_server $server) { } /** * Server正常結(jié)束時的自定義事件處理 * * @param swoole_server $server */ protected function onShutdownHandle(\swoole_server $server) { } /** * 獲取請求路由 * * @param swoole_http_request $request */ protected function getRoute(\swoole_http_request $request) { return ltrim($request->server['request_uri'], '/'); } /** * 獲取請求的GET參數(shù) * * @param swoole_http_request $request */ protected function getParams(\swoole_http_request $request) { return $request->get; } /** * 解析收到的數(shù)據(jù) * * @param string $data */ protected function decodeData($data) { return json_decode($data, true); } /** * Before Exec */ protected function beforeExec() { $startedAt = microtime(true); $this->stdout(date('Y-m-d H:i:s') . "\n", Console::FG_YELLOW); return $startedAt; } /** * After Exec */ protected function afterExec($startedAt) { $duration = number_format(round(microtime(true) - $startedAt, 3), 3); $this->stdout("{$duration} s\n\n", Console::FG_YELLOW); } /** * Prints a string to STDOUT. */ protected function stdout($string) { if (Console::streamSupportsAnsiColors(\STDOUT)) { $args = func_get_args(); array_shift($args); $string = Console::ansiFormat($string, $args); } return Console::stdout($string); } }
三:swoole操作類(繼承swoole基類)
<?php /** * @link http://www.u-bo.com * @copyright 南京友博網(wǎng)絡(luò)科技有限公司 * @license http://www.u-bo.com/license/ */ namespace console\swoole; use Yii; use yii\db\Query; use yii\helpers\Console; use yii\helpers\VarDumper; use apps\sqjc\models\WaterLevel; use apps\sqjc\models\WaterLevelLog; use common\models\Bayonet; use common\models\Device; use common\models\DeviceCategory; /** * Swoole Server測試類 * * @author wangjian * @since 1.0 */ class Server extends BaseServer { /** * @inheritdoc */ public function onConnect($server, $fd, $reactorId) { $startedAt = $this->beforeExec(); $this->stdout("**Connection Open**\n", Console::FG_GREEN); $this->stdout("fd: "); $this->stdout("{$fd}\n", Console::FG_BLUE); $this->afterExec($startedAt); } /** * @inheritdoc */ public function onReceive($server, $fd, $reactorId, $data) { $startedAt = $this->beforeExec(); $this->stdout("**Received Message**\n", Console::FG_GREEN); $this->stdout("fd: "); $this->stdout("{$fd}\n", Console::FG_BLUE); $this->stdout("data: ");//接收的數(shù)據(jù) $this->stdout("{$data}\n", Console::FG_BLUE); $result = $server->send($fd, '回復消息'); $this->afterExec($startedAt); } /** * @inheritdoc */ public function onRequest($request, $response) { $startedAt = $this->beforeExec(); $this->stdout("**HTTP Request**\n", Console::FG_GREEN); $this->stdout("fd: "); $this->stdout("{$request->fd}\n", Console::FG_BLUE); $response->status(200); $response->end('success'); $this->afterExec($startedAt); } /** * @inheritdoc */ public function onClose($server, $fd) { $startedAt = $this->beforeExec(); $this->stdout("**Connection Close**\n", Console::FG_GREEN); $this->stdout("fd: "); $this->stdout("{$fd}\n", Console::FG_BLUE); $this->afterExec($startedAt); } /** * @inheritdoc */ public function onTask($server, $taskId, $srcWorkerId, $data) { $startedAt = $this->beforeExec(); $this->stdout("New AsyncTask: "); $this->stdout("{$taskId}\n", Console::FG_BLUE); $this->stdout("{$data}\n", Console::FG_BLUE); $server->finish($data); $this->afterExec($startedAt); } /** * @inheritdoc */ public function onWorkerStop($server, $worker_id) { // Yii::$app->db->close(); } /** * @inheritdoc */ public function onWorkerStart($server, $worker_id) { // Yii::$app->db->open(); } /** * @inheritdoc */ public function onTaskFinish($server, $taskId, $data) { $startedAt = $this->beforeExec(); $this->stdout("AsyncTask finished: "); $this->stdout("{$taskId}\n", Console::FG_BLUE); $this->afterExec($startedAt); } }
四:操作TCP服務(wù)
<?php /** * @link http://www.u-bo.com * @copyright 南京友博網(wǎng)絡(luò)科技有限公司 * @license http://www.u-bo.com/license/ */ namespace console\controllers; use Yii; use yii\helpers\Console; use yii\helpers\FileHelper; use yii\helpers\ArrayHelper; use console\swoole\Server; /** * WebSocket Server controller. * * @see https://github.com/tystudy/yii2-swoole-websocket/blob/master/README.md * * @author wangjian * @since 1.0 */ class SwooleController extends Controller { /** * @var string 監(jiān)聽IP */ public $host; /** * @var string 監(jiān)聽端口 */ public $port; /** * @var boolean 是否以守護進程方式啟動 */ public $daemon = false; /** * @var boolean 是否啟動測試類 */ public $test = false; /** * @var array Swoole參數(shù)配置項 */ private $_params; /** * @var array Swoole參數(shù)配置項(HTTP協(xié)議) */ private $_http_params; /** * @var array Swoole參數(shù)配置項(TCP協(xié)議) */ private $_tcp_params; /** * @inheritdoc */ public function beforeAction($action) { if (parent::beforeAction($action)) { //判斷是否開啟swoole拓展 if (!extension_loaded('swoole')) { return false; } //獲取swoole配置信息 if (!isset(Yii::$app->params['swoole'])) { return false; } $this->_params = Yii::$app->params['swoole']; $this->_http_params = ArrayHelper::remove($this->_params, 'http'); $this->_tcp_params = ArrayHelper::remove($this->_params, 'tcp'); foreach ($this->_params as &$param) { if (strncmp($param, '@', 1) === 0) { $param = Yii::getAlias($param); } } $this->_params = ArrayHelper::merge($this->_params, [ 'daemonize' => $this->daemon ]); return true; } else { return false; } } /** * 啟動服務(wù) */ public function actionStart() { if ($this->getPid() !== false) { $this->stdout("WebSocket Server is already started!\n", Console::FG_RED); return self::EXIT_CODE_NORMAL; } $server = new Server($this->_http_params, $this->_tcp_params, $this->_params); $server->run(); } /** * 停止服務(wù) */ public function actionStop() { $pid = $this->getPid(); if ($pid === false) { $this->stdout("Tcp Server is already stoped!\n", Console::FG_RED); return self::EXIT_CODE_NORMAL; } \swoole_process::kill($pid); } /** * 清理日志文件 */ public function actionClearLog() { $logFile = Yii::getAlias($this->_params['log_file']); FileHelper::unlink($logFile); } /** * 獲取進程PID * * @return false|integer PID */ private function getPid() { $pidFile = $this->_params['pid_file']; if (!file_exists($pidFile)) { return false; } $pid = file_get_contents($pidFile); if (empty($pid)) { return false; } $pid = intval($pid); if (\swoole_process::kill($pid, 0)) { return $pid; } else { FileHelper::unlink($pidFile); return false; } } /** * @inheritdoc */ public function options($actionID) { return ArrayHelper::merge(parent::options($actionID), [ 'daemon', 'test' ]); } /** * @inheritdoc */ public function optionAliases() { return ArrayHelper::merge(parent::optionAliases(), [ 'd' => 'daemon', 't' => 'test', ]); } }
以上就是php使用swoole實現(xiàn)TCP服務(wù)的詳細內(nèi)容,更多關(guān)于php swoole實現(xiàn)TCP服務(wù)的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
phpQuery采集網(wǎng)頁實現(xiàn)代碼實例
這篇文章主要介紹了phpQuery采集網(wǎng)頁實現(xiàn)代碼實例,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下2020-04-04PHP __autoload函數(shù)(自動載入類文件)的使用方法
在使用PHP的OO模式開發(fā)系統(tǒng)時,通常大家習慣上將每個類的實現(xiàn)都存放在一個單獨的文件里,這樣會很容易實現(xiàn)對類進行復用,同時將來維護時也很便利2012-02-02