流程說明
- 使用 web-msg-sender 作為 伺服器監聽程式。
- 客戶端(瀏覽器)通過websocket連線 伺服器監聽程式。
- 伺服器應用程式(後端) 通過curl訪問 伺服器監聽程式,將需要推送的資訊傳送給 伺服器監聽程式。
- 伺服器監聽程式 接收到後端傳送的資訊,廣播傳送給所有客戶端,提示有新資訊。
- 客戶端 ajax訪問 後端,確認是否有傳送給自己的站內信,如有,播放訊息提示音,並更改頁面站內信未讀數。
文件目錄
[TOC]
伺服器監聽
配置 伺服器監聽程式
該程式對於php環境的要求是:
- php cli >= 5.4,可以執行命令 php -v檢視版本
- linux系統要求php安裝了posix和pcntl擴充套件。
可以使用 curl -Ss http://www.workerman.net/chec… | php 來檢測當前環境是否符合要求。如果不符合,需要根據提示安裝必要的擴充套件。
環境檢測滿足後,以ubuntu配置為例來進行配置:
- 安裝相關擴充套件
$ sudo apt-get install php5-cli git gcc php-pear php5-dev libevent-dev -y
- 安裝event擴充套件,==注意提示:Include libevent OpenSSL support [yes] : 時輸入no回車,其它直接敲回車就行==
$ pecl install event
當出現Include libevent OpenSSL support [yes] :時,輸入no
- 切換到root使用者,新增event.so到php-cli的php-ini檔案中。
$ sudo su
$ echo extension=event.so > /etc/php5/cli/conf.d/event.ini
- 切換回普通使用者,切換到要儲存專案的目錄,clone web-msg-sender專案
$ su nancy
$ cd /var/www
$ git clone https://github.com/walkor/web…
- 使用composer安裝,如果沒有安裝composer,請先安裝。
// 下載composer
$ curl -sS https://getcomposer.org/insta… | php
// 設定全域性
$ sudo mv composer.phar /usr/local/bin/composer
// 檢視是否安裝成功,如果有版本資訊顯示,則說明安裝成功
$ composer -v
// 更新一下
$ composer self-update
// 進入到 web-msg-sender 專案中,使用composer進行安裝
$ cd /var/www/web-msg-sender/
==$ composer install==
開啟伺服器監聽程式
進入該專案檔案,啟動服務(以守護程式方式)
$ php start.php start -d
停止服務
$ php start.php stop
服務狀態
$ php start.php status
客戶端連線
客戶端(即我們的前端程式碼)使用 socket.io 外掛通過websocket連線 伺服器監聽程式。
流程如下:
- 客戶端使用socket建立連線,連線成功後,以使用者實際的user_id傳送登陸請求。
- 登陸請求成功,伺服器監聽程式會以user_id作為使用者的連線標識。
- 當接收到伺服器監聽程式推送的資訊,客戶端傳送請求到後端程式,查詢是否有未讀的站內信。
- 如果有,客戶端播放訊息聲音,並且更新頁面的站內信未讀數。
相關程式碼如下:
// 引入前端檔案
<script src=`//cdn.bootcss.com/socket.io/1.3.7/socket.io.js`></script>
<script>
/*載入提示*/
function loadTip(hit) {
$.ajax({
url: "{{ url(`/message/get_load`) }}",
type: `get`,
success: function(msg) {
if (msg.hit == 1 && hit==1)
//播放訊息提示音
$(".tip-mp3")[0].play();
if (msg.num > 0) {
//顯示未讀訊息數
$(".message-tip").show(500);
$(".message-tip").html(msg.num);
} else
$(".message-tip").hide(500);
}
});
}
// 初始化io物件
var socket = io(`http://your.workerman.com:2120`);
// uid 可以為網站使用者的uid,作為例子這裡用session_id代替
var uid = `{{ Auth::user()->id }} `;
// 當socket連線後傳送登入請求
socket.on(`connect`, function(){socket.emit(`login`, uid);});
// 當服務端推送來訊息時觸發,查詢後端程式
socket.on(`new_msg`, function(msg){loadTip(1);});
// 伺服器端監聽程式推送來線上資料時
socket.on(`update_online_count`, function(online_stat){
$("title").html("ERP "+online_stat);
});
</script>
後端業務處理
後端使用了Laravel第三方外掛Notifynder 管理通知。它提供了一個完整的API來處理通知,例如儲存,檢索和組織程式碼庫以處理數百個通知。
配置 Notifynder 外掛
- 在後端程式的 composer.json 檔案的 require 中增加
"fenos/notifynder": "^4.0"
- 進入後端程式專案,輸入$ composer require fenos/notifynder 整合該外掛。
- 在 config/app.php 檔案的 providers 陣列中增加
FenosNotifynderNotifynderServiceProvider::class,
在 aliases 陣列中增加
`Notifynder` => FenosNotifynderFacadesNotifynder::class,
- 使用一下命令釋出遷移以及配置notifynder
$ php artisan vendor:publish –provider=”FenosNotifynderNotifynderServiceProvider”
$ php artisan migrate
- 在 User Model中使用FenosNotifynderNotifable,以ERP為例,我們的User Model是 app/Erp_company_user.php,在該檔案增加引用。
use FenosNotifynderNotifable;
class Erp_company_user extends Model implements AuthenticatableContract, CanResetPasswordContract {
use Notifable;
}
這時,我們只要使用 Erp_company_user model例項,就可以呼叫 FenosNotifynderNotifable 中的方法。例如:
$user = Erp_company_user::first();
$notifications = $user->notifications;
- 配置 config/notifynder 檔案。
- 在 model 中配置 user model
`model` => `AppErp_company_user`,
其他的根據實際應用時更改配置。
後端業務程式碼
- 提供推送資料到 伺服器監聽程式 的service。
將要推送的資訊和推送的人等相關資料組裝好,使用curl遠端訪問 伺服器監聽程式,監聽程式進行推送。
namespace AppServiceSetting;
use AppServiceCommonService;
class MessageService extends CommonService{
// 指明給誰推送,為空表示向所有線上使用者推送
private $to_uid;
// 推送的url地址,上線時改成自己的伺服器地址
private $push_api_url = `http://your.workerman.com:2121/`;
protected function set_url($push_api_url){
$this->push_api_url=$push_api_url;
}
/**
* 站內信推送
* @param int to_uid
* @return array
*/
public function sent_message($to_uid=``){
$this->to_uid=$to_uid;
$post_data = array(
`type` => `publish`,
`content` => `You have a new message`,
`to` => $this->to_uid,
);
$ch = curl_init ();
curl_setopt ( $ch, CURLOPT_URL, $this->push_api_url );
curl_setopt ( $ch, CURLOPT_POST, 1 );
curl_setopt ( $ch, CURLOPT_HEADER, 0 );
curl_setopt ( $ch, CURLOPT_RETURNTRANSFER, 1 );
curl_setopt ( $ch, CURLOPT_POSTFIELDS, $post_data );
$return = curl_exec ( $ch );
curl_close ( $ch );
return $return;
}
}
- 傳送站內信
客戶端 向 後端程式請求傳送站內信。
後端程式 將站內信資訊儲存到 Notification_category 資料表中,將要指定要推送的人資訊儲存到 notifications 表中。
呼叫 上述的 MessageService 服務將資訊推送到 伺服器監聽程式。
相關程式碼如下:
// 儲存站內信資訊
$Notification_categorie = new Notification_category;
$Notification_categorie->name = $name;
$Notification_categorie->text = $text;
$Notification_categorie->save();
//站內信id
$this->categorie_id=$Notification_categorie->id;
$this->categorie_num=0;
try {
//推送的人,這裡以傳送全體為例
$users = Erp_company_user::all();
//迴圈儲存要通知的人站內信資訊
Notifynder::loop($users, function(NotifynderBuilder $builder, $user, $key) {
$this->categorie_num=$key+1;
$builder->category($this->categorie_id)
->from($this->user[`id`])
->to($user->id);
})->send();
} catch (EntityNotIterableException $e) {
} catch (IterableIsEmptyException $e) {
}
//推送到伺服器端監聽程式
$sent_message = $this->MessageService->sent_message();
- 接收站內信
查詢5分鐘內的站內信,是否有傳送給自己的未讀資訊,有的話,返回未讀資訊數。
相關程式碼如下:
//未讀站內信的數量
$not_read_num=$this->user->countNotificationsNotRead();
//是否提示新資訊,看最新的站內信的時間是否在5分鐘內
$message=$this->user->getLastNotification();
if(empty($message))
return array(`num`=>0,`hit`=>0);
$message_time=$message->updated_at;
$five_minute_ago= Carbon::parse(`-5 minute`);
($message_time->gt($five_minute_ago) && $message->read==0 )? $hit=1 : $hit=0;
$result_array=array(`num`=>$not_read_num,`hit`=>$hit);
return $result_array;