Linux下搭建swoole實現(xiàn)php消息推送的方法
Swoole使用純C語言編寫,提供了PHP語言的異步多線程服務(wù)器,異步 TCP/UDP 網(wǎng)絡(luò)客戶端,異步 MySQL,異步 Redis,數(shù)據(jù)庫連接池,AsyncTask,消息隊列,毫秒定時器,異步文件讀寫,異步DNS查詢。 Swoole內(nèi)置了Http/WebSocket服務(wù)器端/客戶端、Http2.0服務(wù)器端,完美支持PHP語言。本文講解Linux下搭建swoole實現(xiàn)php消息推送的方法。
swoole簡介
Swoole是一個面向生產(chǎn)環(huán)境的 PHP 異步網(wǎng)絡(luò)通信引擎,使 PHP 開發(fā)人員可以編寫高性能的異步并發(fā) TCP、UDP、Unix Socket、HTTP,WebSocket 服務(wù)。Swoole 可以廣泛應(yīng)用于互聯(lián)網(wǎng)、移動通信、企業(yè)軟件、云計算、網(wǎng)絡(luò)游戲、物聯(lián)網(wǎng)(IOT)、車聯(lián)網(wǎng)、智能家居等領(lǐng)域。 使用 PHP + Swoole 作為網(wǎng)絡(luò)通信框架,可以使企業(yè) IT 研發(fā)團(tuán)隊的效率大大提升。
Swoole不是一個像Zend Framework、CakePHP、Yii、symfony、ThinkPHP等一樣的框架,也不是一個像WordPress、Drupal、Discuz、UChome等開源產(chǎn)品看齊的項目。 Swoole的目標(biāo)是向Java框架、Ruby On Rails、Python DjangoPylons等一流框架發(fā)起挑戰(zhàn)。
Swoole雖然是標(biāo)準(zhǔn)的PHP擴(kuò)展,實際上與普通的擴(kuò)展不同。普通的擴(kuò)展只是提供一個庫函數(shù)。而Swoole擴(kuò)展在運(yùn)行后會接管PHP的控制權(quán),進(jìn)入事件循環(huán)。當(dāng)IO事件發(fā)生后底層會自動回調(diào)指定的PHP函數(shù)。
包含以下幾個特色功能:
1、 類似ORM的數(shù)據(jù)查詢,提供SQL封裝器,讓MySQL的SQL與PHP的Array,會話,Cache無縫結(jié)合。
2、App MVC分層結(jié)構(gòu),有效的程序結(jié)構(gòu)分層,提高程序的可維護(hù)性和擴(kuò)展性,實現(xiàn)低耦合,基于接口開發(fā)。
3、集成大量,實用的功能,比如方便的數(shù)據(jù)庫操作,模板操作,緩存操作,系統(tǒng)配置,表單處理,分頁,數(shù)據(jù)調(diào)用,字典操作,上傳處理,內(nèi)容編輯,調(diào)試等。
4、模板-數(shù)據(jù)反射系統(tǒng),可以直接在模板中調(diào)用數(shù)據(jù),提供很多標(biāo)簽,可以無需修改程序,只修改模板,即可實現(xiàn)網(wǎng)站各類更新維護(hù)工作。
另外的幾個功能
1、Swoole包含了大量類,提供眾多的功能擴(kuò)展,基本上Web開發(fā)能夠用到的功能類,大部分都可以在Swoole框架中找到。
2、Swoole擁有插件系統(tǒng),F(xiàn)ckeditor、Adodb、pscws中文分詞、中文全文索引系統(tǒng)、最新的Key-Value數(shù)據(jù)庫思想,TokyoTyrant,可以無限擴(kuò)展框架的功能。
安裝swoole服務(wù)
1.下載swoole源碼,下載地址: https://github.com/swoole/swoole-src/releases
2.將tar包上傳到/usr/local/src/swoole下面,這里面存儲安裝源文件。
3.解壓源文件,tar –xvfswoole.tar
4.進(jìn)入到剛解壓的目錄下輸入命令phpize
5.注意:phpize是php-devel中的東西,它可以給PHP動態(tài)添加擴(kuò)展,所以,請確保你的機(jī)器上安裝了php-devel軟件包。
6.接著,依次輸入如下命令:./configure,執(zhí)行編譯檢測make,編譯swoole
7.缺少pcre和pcre-devel相關(guān)軟件包,安裝上即可。
8.sudo make install
9.php.ini一般在etc下面 編譯安裝成功后,我們還需要修改php.ini,在其中加入swoole.so擴(kuò)展:
10.extension=swoole.so
11.輸入php -m中能查看到swoole說明擴(kuò)展安裝成功。
安裝apache啟動swoole服務(wù)
(1)測試是否安裝正確啟動swoole Php服務(wù)
(2)在apache中添加server.php文件,和client.php文件。一般目錄在var/www/html下面
(3)打開兩個終端 在這兩個文件所在的目錄下面打開這兩個文件,可以實現(xiàn)socket長連接服務(wù)。
安裝lsof:yum -y install lsof
Server端PHP程序
class WebSocketService {
private static $instance = NULL;
public $tagindex = 0;
public $server = null;
public $office_cache = null;
public $timer_arr = []; //該變量保存所有的定時器任務(wù)ID,每一個客戶端可以通過$timer_arr[客戶端ID]
得到該客戶端建立的所有定時器
public $conf = [
'host' => '0.0.0.0',
'port' => 9999, //服務(wù)使用端口
'worker_num' => 2, //啟動worker進(jìn)程數(shù)
'task_worker_num' => 8, //啟動task進(jìn)程數(shù)
'is_daemonize' => 0, //是否后臺運(yùn)行:0-否,1-是
'log_file' =>'/tmp/swoole_webSocket_server.log', //日志文件路徑
'abc' =>0,
];
public function getTagIndex() {
return $this->conf['abc'];
}
public function setSetTagIndex($index) {
$this->conf['abc'] = 100;
echo $this->getTagIndex();
}
public function __construct($config = []) {
$this->office_cache = array('1' => '1', '3'=>'2');
$this->conf = array_merge($this->conf, (array)$config);
}
//靜態(tài)方法,返回此類唯一實例
public static function getInstance(){
if(empty(self::$instance)){
echo "instance \n";
self::$instance=new WebSocketService();
}
return self::$instance;
}
/**
* 服務(wù)器端運(yùn)行webSocket的入口
*/
public function run() {
try {
$this->server = new \swoole_websocket_server($this->conf['host'],$this->conf['port']);
$this->server->set(
[
'worker_num' => $this->conf['worker_num'],
'task_worker_num' =>$this->conf['task_worker_num'],
'daemonize' => $this->conf['is_daemonize'],
'log_file' => $this->conf['log_file'],
]
);
//注冊方法列表
$this->server->on('open', [$this, 'open']);
$this->server->on('message', [$this, 'message']);
$this->server->on('task', [$this, 'task']);
$this->server->on('finish', [$this, 'finish']);
$this->server->on('close', [$this, 'close']);
$this->server->start();
} catch (\Exception $e) {
var_dump($e->getCode() . ':' . $e->getMessage());
}
}
/**
* 建立socket鏈接時,執(zhí)行方法
* @param $server
* @param $request
*/
public function open($server, $request) {
$data = [
'client_id' => $request->fd,
'request' => $request
];
echo 'open<<'.$data['client_id'];
$this->doOpen($data);
}
/**
* 發(fā)送消息時,執(zhí)行方法
* @param $server
* @param $frame
*/
public function message($server, $frame) {
echo "GET_mesage\n";
$data = [
'client_id' => $frame->fd,
'data' => $frame->data,
'frame' => $frame,
];
$this->doMessage($data);
}
/**
* 執(zhí)行具體任務(wù)
* @param $server
* @param $task_id
* @param $from_id
* @param $data
*/
public function task($server, $task_id, $from_id, $data) {
$data['task_id'] = $task_id;
$data['from_id'] = $from_id;
$this->doTask($data);
}
/**
* 任務(wù)結(jié)果處理
* @param $server 服務(wù)器對象
* @param $taskId 任務(wù)進(jìn)程ID
* @param $data
*/
public function finish($server, $taskId, $data) {
$data['task_id'] = $taskId;
$this->doFinish($data);
}
/**
* 關(guān)閉鏈接
* @param $server 服務(wù)器對象
* @param $client_id 客戶端唯一標(biāo)識
*/
public function close($server, $client_id) {
$data = [
'client_id' => $client_id
];
$this->doClose($data);
}
/**
* 客戶端成功連接到服務(wù)器時,會觸發(fā)該方法
* 子類根據(jù)需求重寫該方法
* @param $data
* [
* 'client_id', //客戶端唯一標(biāo)識
* 'data', //一些請求數(shù)據(jù)
* 'frame', //swoole的數(shù)據(jù)
* ];
*/
public function doOpen($data) {
echo "建立連接成功";
}
/**
* 得到Swoole Websocket Server
*
* @return null|\swoole_websocket_server
*/
public function getServer()
{
return $this->server;
}
/**
* 收到客戶端發(fā)來的消息,會觸發(fā)該方法
* 子類根據(jù)需求重寫該方法
* @param $data
* [
* 'client_id', //客戶端唯一標(biāo)識
* 'data', //客戶端發(fā)送過來的消息(數(shù)據(jù))
* 'frame', //swoole的數(shù)據(jù)
* ];
*/
public function doMessage($data) {
$info = json_decode($data['data'],true);
$officeid = $info['officeid'];
$client_id = $data['client_id'];
echo"<<<<".$officeid.">>>>".$client_id."\r\n";
if ($officeid == 1) {
$this->sendMsgToClient('2',array('msg' =>'我是1號場地發(fā)送給你數(shù)據(jù)'));
} else {
$this->sendMsgToClient('1',array('msg' =>'我是3號場地發(fā)送給你數(shù)據(jù)'));
}
}
/**
* 具體的工作任務(wù)。需要通過 $this->doJob()來觸發(fā)
* 子類根據(jù)需求重寫該方法
* @param $data
* [
* 'client_id', //客戶端唯一標(biāo)識
* ];
*/
public function doTask($data) {
}
/**
* 工作的結(jié)果處理。
* 子類根據(jù)需求重寫該方法
* @param $data
* [
* 'client_id', //客戶端唯一標(biāo)識
* ];
*/
public function doFinish($data) {
}
/**
* 客戶端斷開時會自動觸發(fā)該方法
* 子類根據(jù)需求重寫該方法
* @param $data
* [
* 'client_id', //客戶端唯一標(biāo)識
* ];
*/
public function doClose($data) {
}
/**
* 發(fā)送任務(wù)
* @param $data 必須是數(shù)組,且要有$data['client_id']
*/
public function doJob($data) {
$this->server->task($data);
}
public function finishJob($data) {
$this->server->finish($data);
}
/**
* 發(fā)送消息到客戶端
* @param $client_id
* @param $msg
*/
public function sendMsgToClient($client_id, $msg) {
echo "發(fā)送信息給客戶端:{$client_id} | {$msg['action']['name']} | " . date('Y-m-dH:i:s') . "\r\n";
$this->server->push($client_id, json_encode($msg));
}
/**
* 關(guān)閉客戶端鏈接
* @param $client_id
*/
public function closeClient($client_id) {
$this->server->close($client_id);
}
/**
* 添加定時器
* @param $client_id
* @param $tick_time
*/
public function addTimer($client_id, $tick_time) {
//暫未實現(xiàn),先使用swoole原生寫法
}
/**
* 清除定時器
* @param $client_id
* @param $arr
*/
public function clearTimer($client_id, &$arr) {
if (is_array($arr)) {
foreach ($arr[$client_id] as $val) {
if (is_array($val)) {
foreach ($val as $v) {
swoole_timer_clear($v);
}
} else {
swoole_timer_clear($val);
}
}
}
unset($arr[$client_id]);
}
}html前端javascript程序
$(document).ready(function(){
varwsurl = "ws://182.92.101.206:9999/";
console.log(wsurl);
varwebsocket = new WebSocket(wsurl);
websocket.onopen= function(evt){
console.log('Server: 打開WebSocket連接');
};
websocket.onclose= function(evt){
console.log('Server: 關(guān)閉WebSocket連接');
};
websocket.onmessage= function(evt){
varres = JSON.parse(evt.data);
console.log('Server: 收到消息(來自:'+res+'請求)');
console.log(res);
};
websocket.οnerrοr= function(evt){
console.log('Server: 出現(xiàn)錯誤');
console.log(evt.data);
}
functiondoSend(msg){
console.log('Client:發(fā)送消息 ' + msg);
websocket.send(msg);
}
});啟動start.php文件
啟動start.php文件,cd到指定目錄下,然后PHP-CLI運(yùn)行php start.php。這種方式是沒有啟用線程保護(hù)的關(guān)掉后程序結(jié)束線程還在占用。
require'src/WebSocketSwoole/WebSocketService.php'; // require './WebSocketService.php'; session_start(); // $demoService = new\WebSocketSwoole\WebSocketService(); $demoService =\WebSocketSwoole\WebSocketService::getInstance(); $demoService->run();
總結(jié)
到此這篇關(guān)于Linux下搭建swoole實現(xiàn)php消息推送的方法的文章就介紹到這了,更多相關(guān)swoole實現(xiàn)php消息推送內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
php實現(xiàn)兼容2038年后Unix時間戳轉(zhuǎn)換函數(shù)
這篇文章主要介紹了php實現(xiàn)兼容2038年后Unix時間戳轉(zhuǎn)換函數(shù),使用方法和就的函數(shù)一樣,非常實用,推薦給大家,希望大家能夠喜歡。2015-03-03
無需數(shù)據(jù)庫在線投票調(diào)查php代碼
這篇文章主要為大家詳細(xì)介紹了無需數(shù)據(jù)庫在線投票調(diào)查php代碼2016-07-07
PHP Laravel 使用Swagger生成API文檔(基本概念和環(huán)境搭建)
Swagger是一種簡單、強(qiáng)大的RESTful API表現(xiàn)形式,這篇文章主要介紹了PHP Laravel 使用Swagger生成API文檔(基本概念和環(huán)境搭建),需要的朋友可以參考下2023-09-09
PHP基于CURL進(jìn)行POST數(shù)據(jù)上傳實例
這篇文章主要介紹了PHP基于CURL進(jìn)行POST數(shù)據(jù)上傳的方法,以完整的實例形式較為詳細(xì)的講述了PHP采用curl進(jìn)行POST數(shù)據(jù)傳遞的方法,具有一定的參考借鑒價值,需要的朋友可以參考下2014-11-11
如何用phpmyadmin設(shè)置mysql數(shù)據(jù)庫用戶的權(quán)限
發(fā)現(xiàn)有很多用戶對數(shù)據(jù)庫用戶權(quán)限的設(shè)置不太了解,下面為大家詳細(xì)講解一下如何用 phpMyAdmin 來設(shè)置數(shù)據(jù)庫用戶的權(quán)限2012-01-01
Zend Framework教程之Bootstrap類用法概述
這篇文章主要介紹了Zend Framework教程之Bootstrap類用法,簡單分析了Bootstrap的功能,定義,相關(guān)參數(shù)與使用方法,需要的朋友可以參考下2016-03-03

