流程说明
客户端(浏览器)通过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
使用composer安装,如果没有安装composer,请先安装。
// 下载composer
// 设置全局
$ 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作为用户的连接标识。
当接收到服务器监听程序推送的信息,客户端发送请求到后端程序,查询是否有未读的站内信。
如果有,客户端播放消息声音,并且更新页面的站内信未读数。
相关代码如下:
// 引入前端文件
/*加载提示*/
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);
});
后端业务处理
后端使用了Laravel第三方插件Notifynder 管理通知。它提供了一个完整的API来处理通知,例如存储,检索和组织代码库以处理数百个通知。
配置 Notifynder 插件
在后端程序的 composer.json 文件的 require 中增加
"fenos/notifynder": "^4.0"
进入后端程序项目,输入$ composer require fenos/notifynder 集成该插件。
在 config/app.php 文件的 providers 数组中增加
Fenos\Notifynder\NotifynderServiceProvider::class,
在 aliases 数组中增加
'Notifynder' => Fenos\Notifynder\Facades\Notifynder::class,
使用一下命令发布迁移以及配置notifynder
$ php artisan vendor:publish --provider="FenosNotifynderNotifynderServiceProvider"
$ php artisan migrate
在 User Model中使用FenosNotifynderNotifable,以ERP为例,我们的User Model是 app/Erp_company_user.php,在该文件增加引用。
use Fenos\Notifynder\Notifable;
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' => 'App\Erp_company_user',
其他的根据实际应用时更改配置。
后端业务代码
提供推送数据到 服务器监听程序 的service。
将要推送的信息和推送的人等相关数据组装好,使用curl远程访问 服务器监听程序,监听程序进行推送。
namespace App\Service\Setting;
use App\Service\CommonService;
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;