php使用swoole實現(xiàn)TCP服務
更新時間:2024年04月03日 08:31:09 作者:huaweichenai
這篇文章主要為大家詳細介紹了php如何使用swoole實現(xiàn)TCP服務,文中的示例代碼講解詳細,具有一定的借鑒價值,有需要的小伙伴可以參考一下
這里以在Yii框架下示例
一:swoole配置TCP
'swoole' => [
// 日志文件路徑
'log_file' => '@console/log/swoole.log',
// 設置swoole_server錯誤日志打印的等級,范圍是0-5。低于log_level設置的日志信息不會拋出
'log_level' => 1,
// 進程的PID存儲文件
'pid_file' => '@console/log/swoole.server.pid',
// HTTP協(xié)議配置
'http' => [
'host' => '0.0.0.0',
'port' => '8889',
// 異步任務的工作進程數(shù)量
'task_worker_num' => 4,
],
// TCP協(xié)議配置
'tcp' => [
'host' => '0.0.0.0',
'port' => '14000',
// 異步任務的工作進程數(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服務基類
<?php
/**
* @link http://www.u-bo.com
* @copyright 南京友博網(wǎng)絡科技有限公司
* @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);
}
/**
* 客戶端與服務器建立連接后的回調(diào)事件處理
*
* @param swoole_server $server
* @param integer $fd
* @param integer $reactorId
*/
abstract public function onConnect(\swoole_server $server, int $fd, int $reactorId);
/**
* 當服務器收到來自客戶端的數(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);
/**
* 當服務器收到來自客戶端的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);
/**
* 異步任務處理
*
* @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);
/**
* 異步任務處理完成
*
* @param swoole_server $server
* @param integer $taskId
* @param mixed $data
*/
abstract public function onTaskFinish(\swoole_server $server, int $taskId, mixed $data);
/**
* 客戶端與服務器斷開連接后的回調(diào)事件處理
*
* @param swoole_server $server
* @param integer $fd
*/
abstract public function onClose(\swoole_server $server, $fd);
/**
* Server正常結束時的回調(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正常結束時的自定義事件處理
*
* @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)絡科技有限公司
* @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服務
<?php
/**
* @link http://www.u-bo.com
* @copyright 南京友博網(wǎng)絡科技有限公司
* @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;
}
}
/**
* 啟動服務
*/
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();
}
/**
* 停止服務
*/
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服務的詳細內(nèi)容,更多關于php swoole實現(xiàn)TCP服務的資料請關注腳本之家其它相關文章!
相關文章
phpQuery采集網(wǎng)頁實現(xiàn)代碼實例
這篇文章主要介紹了phpQuery采集網(wǎng)頁實現(xiàn)代碼實例,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下2020-04-04
PHP __autoload函數(shù)(自動載入類文件)的使用方法
在使用PHP的OO模式開發(fā)系統(tǒng)時,通常大家習慣上將每個類的實現(xiàn)都存放在一個單獨的文件里,這樣會很容易實現(xiàn)對類進行復用,同時將來維護時也很便利2012-02-02

