redis缓存聊天消息

首页 编程分享 PHP丨JAVA丨OTHER 正文

袅袅牧童 推荐 原创 编程分享 2019-10-25 10:19:31

简介 博客用gatewayworker做了个站内通讯,这几天有网友问后台消息的处理逻辑,这里把redis消息处理的源码拿出来,需要的可以参考下。


第一次搞gatewayworker,看了看官方手册,自己想了想,一步步就搞成这样了,可以参考下该表情版权归腾讯公司所有!

后台逻辑代码:

class Comit extends API_Controller
{
protected $redis;
protected $user_id;
public function __construct()
{
parent::__construct();
$this->load->driver('cache'); //这是ci的缓存类;
$this->redis = $this->cache->redis;
$this->user_id = isset($_SESSION['user_id']) ? $_SESSION['user_id'] : null;
if(! $this->user_id){
$this->ajax_return(201,MESSAGE_ERROR_NOT_SIGN);
};
}

public function index()
{
$uId = $this->uri->segment(2, 0);
switch (REQUEST_METHOD) {
case REQUEST_POST:
if ((int) $uId) {
$this->community_add($uId);
}
break;
case REQUEST_GET:
if ((int) $uId) {
$this->community_list($uId);
}
break;
}
}

//获取联系人列表;
public function comit_user_list()
{
$aUser = $this->redis->get('cUser:' . $this->user_id);
if ($aUser) {
$time = $this->redis->get('comitCancel:' . $this->user_id);
$time = $time ? $time : 1;
// var_dump($time);
krsort($aUser);
$uData = array_flip($aUser);
$sIds = join(',', $aUser);
$sql = "SELECT user_id,user_name,photo FROM mt_user WHERE user_id in ({$sIds})";
$aData = $this->db->query($sql)->result_array();

$dataMsgs = $this->redis->get('comitIn:' . $this->user_id);
//返回联系人列表;
foreach ($aData as $K => $v) {
$temp = $uData[$v['user_id']]; //加入联系人时间;
$uData[$v['user_id']] = array();
$uData[$v['user_id']]['user_name'] = $v['user_name'];
$uData[$v['user_id']]['photo'] = $v['photo'];
$uData[$v['user_id']]['user_id'] = $v['user_id'];
$uData[$v['user_id']]['new'] = 2;
if ($temp > $time) { //判断是否新消息;
$uData[$v['user_id']]['new'] = 1;
isset($dataMsgs[$temp]) && $dataMsgs[$temp]['id'] == $v['user_id'] ? $uData[$v['user_id']]['newMsg'] = $dataMsgs[$temp]['msg'] : '';
}
$uData[$v['user_id']]['time'] = date('m-d H:i', $temp);
}
$this->ajax_return(200, MESSAGE_SUCCESS, $uData);
}
$this->ajax_return(201, MESSAGE_ERROR_NO_MSG);
}
//获取历史消息 public function comit_story()
{
$uid = $this->input->get('uid');
$mData = $this->redis->get('comitOut:' . $this->user_id);
$yData = $this->redis->get('comitIn:' . $this->user_id);
$uData = array();
$time = $this->redis->get('comitCancel:' . $this->user_id);
$time = $time ? $time : 1;
//我发送的;
if ($mData) {
foreach($mData as $K=>$v){
if($K < $time && $v['id'] == $uid){
$uData[$K] = $v;
$uData[$K]['from']=$this->user_id;
$uData[$K]['time']=date('m-d H:i',$K);
}
}
}
//我接受的;
if ($yData) {
foreach($yData as $K=>$v){
if($K < $time && $v['id'] == $uid){
$uData[$K] = $v;
$uData[$K]['from']=$uid;
$uData[$K]['time']=date('m-d H:i',$K);
}
}
}
if (!empty($uData)) {
$this->ajax_return(200, MESSAGE_SUCCESS,$uData );
} else {
$this->ajax_return(201, MESSAGE_ERROR_NO_MSG_STORY);
}
}

//获取最新信息情况;
public function comit_new_status()
{
//先获取最后的关闭时间;
$time = $this->redis->get('comitCancel:' . $this->user_id);
if ($time) {
//写给我的;
$inData = $this->redis->get('comitIn:' . $this->user_id);
if ($inData) {
//我写给别人的;
$data = array_keys($inData);
$a = end($data);
if ($a > $time) {
$this->ajax_return(200, MESSAGE_SUCCESS);
}
}
} else {
$this->redis->save('comitCancel:' . $this->user_id, 1);
}
$this->ajax_return(201, MESSAGE_SUCCESS); //头次登陆无时间;
}

//获取和某人联系的信息,默认取在我退出之后得到的;old参数则取历史消息;
protected function community_list($uid)
{
$time = $this->redis->get('comitCancel:' . $this->user_id);
$newData = $this->redis->get('comitIn:' . $this->user_id);
if ($newData) {
$_newData = array();
//遍历缓存消息;
foreach ($newData as $K => $v) {
if ($K > $time && $v['id'] == $uid) {
$v['time'] = date('m-d H:i',$K);
$_newData[$K] = $v;
}
}
if (!empty($_newData)) {
$this->ajax_return(200, MESSAGE_SUCCESS, $_newData);
}
}
$this->ajax_return(201, MESSAGE_ERROR_NO_MSG);
}

//user 和消息的添加;
protected function community_add($uId)
{
if ($uId == $this->user_id) {
$this->ajax_return(201, MESSAGE_ERROR_DATA_WRITE);
}
$msg = $this->input->post('msg');
$nowTime = time();
//设定联系人数组;
//我的联系人组serialize array(time=>id);
$mData = $this->redis->get('cUser:' . $this->user_id);
if ($mData) {
$_mData = array_flip($mData); //反转数组;
if (!isset($_mData[$uId])) {
$mData[$nowTime] = $uId;
} else {
$_mData[$uId] = $nowTime;
$mData = array_flip($_mData);
}
$this->redis->save('cUser:' . $this->user_id, $mData);
} else {
$this->redis->save('cUser:' . $this->user_id, array($nowTime => $uId));
}

//对方的联系人组;
$uData = $this->redis->get('cUser:' . $uId);
if ($uData) {
$_uData = array_flip($uData);
if (!isset($_uData[$this->user_id])) {
$uData[$nowTime] = $this->user_id;
} else {
$_uData[$this->user_id] = $nowTime;
$uData = array_flip($_uData);
}
$this->redis->save('cUser:' . $uId, $uData);
} else {
$this->redis->save('cUser:' . $uId, array($nowTime => $this->user_id));
}

// 缓存消息;
if (isset($msg) && !empty($msg)) {
//接受方
$dataIn = $this->redis->get('comitIn:' . $uId);
if ($dataIn) {
$dataIn[$nowTime] = array('id' => $this->user_id, 'msg' => $msg, 'photo' => $_SESSION['user_photo']);
} else {
$dataIn = array($nowTime => array('id' => $this->user_id, 'msg' => $msg, 'photo' => $_SESSION['user_photo']));
}
$this->redis->save('comitIn:' . $uId, $dataIn, 86400 * 7);
//发出方;
$dataOut = $this->redis->get('comitOut:' . $this->user_id);
if ($dataOut) {
$dataOut[$nowTime] = array('id' => $uId, 'msg' => $msg, 'photo' => $_SESSION['user_photo']);
} else {
$dataOut = array($nowTime => array('id' => $uId, 'msg' => $msg, 'photo' => $_SESSION['user_photo']));
}
$this->redis->save('comitOut:' . $this->user_id, $dataOut, 86400 * 7);
}
$this->ajax_return(200, MESSAGE_SUCCESS);
}


//记录关闭时间;
public function comitCancel()
{
if (REQUEST_METHOD !== REQUEST_POST) $this->ajax_return(400, MESSAGE_ERROR_REQUEST_TYPE);
$res = $this->redis->save('comitCancel:' . $this->user_id, time());
if ($res) {
$this->ajax_return(200, MESSAGE_SUCCESS);
} else {
$this->ajax_return(201, MESSAGE_ERROR_DATA_WRITE);
}
}
}

这是前台处理逻辑:

var comitStat = false, //是否开启聊天窗口
 base64 = new Base64(), //消息base64序列化
 fromPhoto = ''; 
$(function () {
if (uid) {
//ajax获取最新信息情况;
if (!comitStat) {
$.ajax({
url: "/comit/comit_new_status",
type: "get",
success: function (e) {
if (e.code == 200) {
$('IdmewComit').css('opacity', '1'); //这个是页面新消息提示 red dot;
}
}
})
}
// 建立WebSocket链接;
ws = new WebSocket("ws://******:8282"); //这是我本地虚拟机地址 ,外网https 我做的nginx代理,稍后说;
ws.onmessage = function (e) {
//json数据转换成js对象
var e = eval("(" + e.data + ")");
var type = e.type || '';
switch (type) {
// Events.php中返回的init类型的消息,将client_id发给后台进行uid绑定
case 'init':
var bind = '{"type":"bind","fromid":' + uid + '}';
ws.send(bind);
break;
case 'ping': break; //这是心跳检测; default:
//text;打印消息;
if (!comitStat) {
$('IdmewComit').css('opacity', '1'); //提示消息
} else {
//窗口打开状态,依照toid和from以及目前的选中状态写进div消息;
if (!$('IdmyCommunity Idcomitto' + e.from).hasClass('usrBack')) {
//联系人列表,非选中给红点;
$('IdmyCommunity Idcomitto' + e.from + ' i').css('opacity', '1');
if (userver) {
$('IdmyCommunity Idcomitto' + e.from + ' p:last-child').html(base64.decode(e.data));
}
} else {
//检查上条时间;
let ctime = mtNowTime();
let ntime = $('IdmyCommunity Idctime input').val();
let ctimeValue = new Date().getTime();
if (!ntime || ctimeValue > ntime + 1800) {
$('IdmyCommunity IdcommunityMsg').append('<p id="ctime" ><input type="hidden" value="' + ctimeValue + '">' + ctime + '</p>');
}
$('IdmyCommunity IdcommunityMsg').append('<div class="comitmsg-y"><div class="comitmsg-user-y"><img class="comit-top-profiles" src="' + fromPhoto + '"></div><div class="comitmsg-msg-y">' + base64.decode(e.data) + '</div></div><hr id="' + ctimeValue + '">');
if (userver) {
$('IdmyCommunity Idcomitto' + e.from + ' p:last-child').html(base64.decode(e.data));
}
document.getElementById(ctimeValue).scrollIntoView(false);//滚动到底部;
}
}
break;
}
}
}
});
//打开聊天窗口;
function communityConnect(toid = false) {
if (!uid) return Login();
if (comitStat) return false;
//手动点击获取最新消息;
if (toid) {
open_comit(toid);
} else {
$.ajax({
// 获取联系人列表
url: "/comit/comit_user_list",
type: "get",
success: function (e) {
if (e.code == 200) {
open_comit(e);
} else {
alert('暂无消息', 5);
}
}
});
}
}

function open_comit(e) {
comitStat = true;
let cwidth = userver ? '60%' : '95%';
var comitDiv = layer.open({
area: [cwidth, "90%"],
id: 'myCommunity',
resize: true,
title: ["<img class='comit-top-profiles' src='" + photo + "'> " + name, "font-size:14px;"],
offset: "t",
closeBtn: 1,
content: $('IdcommunityTemplate ').html(),
btn: false,
cancel: function (index) {
comitStat = false;
//记录关闭时间;
$.ajax({
url: "/comit/comitCancel",
type: "post",
success: function (e) {
if (e.code != 200) {
alert(e.msg, 5);
}
}
})
layer.close(comitDiv);
}
}) //绑定键盘Esc关闭聊天窗口; $(document).keyup(function (e) {
if (e.which == 27) {
//记录关闭时间
comitStat = false;
$.ajax({
url: "/comit/comitCancel",
type: "post",
success: function (e) {
if (e.code == 200) {
layer.close(comitDiv);
} else {
alert(e.msg, 5);
}
}
})
}
})
var news = '<i class="layui-icon layui-badge-dot" style="position:absolute;opacity:0;"></i>';
let userInfo = '';
if (e.data) {
//添加联系人;
$.each(e.data, function (i, o) {
if (o.user_id) {
if (userver) {
let newMsg = o.newMsg ? base64.decode(o.newMsg) : o.time;
userInfo = '<p>' + o.user_name + '</p><p>' + newMsg + '</p>';
}
$('IdmyCommunity IdcommunityUser').append('<li id="comitto' + o.user_id + '" onclick="comitTo(' + o.user_id + ')"><input type="hidden" value="' + o.user_id + '">' + news + '<img src="' + o.photo + '" class="comit-top-profiles">' + userInfo + '</li>');
}
})
} else {
//获取对应用户信息;
$.ajax({
url: "/user/"+e,
type: "get",
success: function (e) {
if (e.code == 200) {
let o = e.data;
let ctime = mtNowTime();
userInfo = '<p>' + o.user_name + '</p><p>' + ctime + '</p>';
$('IdmyCommunity IdcommunityUser').append('<li id="comitto' + o.user_id + '" onclick="comitTo(' +o.user_id+ ')"><input type="hidden" value="' + o.user_id + '">' + news + '<img src="' + o.photo + '" class="comit-top-profiles">' + userInfo + '</li>');
comitTo(o.user_id);
}
}
})
}

$('IdmewComit').css('opacity', '0');
$('IdmyCommunity').parent().css('margin-top', '50px');
loadScript('/js/editor/wangEditor.js', function () { //这是我的编辑器载入。。。。
wangEditorStart(!1, "Idceditor");
$('Idceditor>div:first-child div:first-child,Idceditor>div:first-child div:nth-child(2),Idceditor>div:first-child div:nth-child(4),Idceditor>div:first-child div:nth-child(5)').remove();
});

document.getElementById("myCommunity").addEventListener('keyup',function(e){
var toid = $("IdmyCommunity IdcommunityUser li[class$='usrBack'] input").val();
if (toid) {
if (e.which == 13) {
addComit(toid);
}
}
});

$('IdmyCommunity IdceditorBtn').on('click', function () {
var toid = $("IdmyCommunity IdcommunityUser li[class$='usrBack'] input").val();
if (toid) {
addComit(toid);
}
})
}
//发送消息处理
function comitTo(toid) {
if (!uid) return Login();
if (comitStat) {
$('IdmyCommunity IdcommunityUser li').removeClass('usrBack');
if (toid && toid != uid) {
//开始载入聊天记录;暂定去上次退场的消息;
$.ajax({
//记录缓存;
url: "/comit/" + toid,
type: "get",
success: function (e) {
if (e.code == 200) {
//检查上条时间;
let ctime = mtNowTime();
let ntime = $('IdmyCommunity Idctime input').val();
let ctimeValue = new Date().getTime();
if (!ntime || ctimeValue > ntime + 1800) {
$('IdmyCommunity IdcommunityMsg').append('<p id="ctime" ><input type="hidden" value="' + ctimeValue + '">' + ctime + '</p>');
}
$.each(e.data, function (i, o) {
$('IdmyCommunity IdcommunityMsg').append('<div class="comitmsg-y"><div class="comitmsg-user-y"><img class="comit-top-profiles" src="' + o.photo + '"></div><div class="comitmsg-msg-y">' + base64.decode(o.msg) + ' <font style="color:Idb3b3b3;font-size:x-small">' + o.time + '</font></div></div><hr id="' + ctimeValue + '">');
})
document.getElementById(ctimeValue).scrollIntoView(false);//滚动到底部;
}
}
})
}
} else {
communityConnect(toid);
}
}
//发送消息;
function addComit(toid) {
var msg = $('Idceditor .w-e-text').html();
msg = msg.replace(/<p><br><\/p>/g, '').replace(/<div><\/div>/g, '').replace(/<p><\/p>/g, '').replace(/<br>/g, '').replace(/<p>/g,'').replace(/<\/p>/g,'');
if (msg.replace(/\s/g, "") == '' || msg.replace(/\s/g, "").replace(/ /g, "").replace(/<br>/g, '').replace(/<p><\/p>/g, '').replace(/<div>/g, '').replace(/<\/div>/g, '') == '') {
$('Idceditor .w-e-text').html('');
layer.tips('您还没有输入内容', "IdmyCommunity IdceditorBtn", {
tips: [4, "Id333"]
})
return;
}
var msgs = base64.encode(msg);
$.ajax({
//记录缓存;
url: "/comit/" + toid,
type: "post",
data: {
'msg': msgs
},
success: function (e) {
if (e.code == 200) {
$('Idceditor .w-e-text').html('');
var message = '{"data":"' + msgs + '","type":"say","fromid":"' + uid + '","toid":"' + toid + '"}';
ws.send(message);
//检查上条时间;
let ctime = mtNowTime();
let ntime = $('IdmyCommunity Idctime input').val();
let ctimeValue = new Date().getTime();
if (!ntime || ctimeValue > ntime + 1800) {
$('IdmyCommunity IdcommunityMsg').append('<p id="ctime" ><input type="hidden" value="' + ctimeValue + '">' + ctime + '</p>');
}
$('IdmyCommunity IdcommunityMsg').append('<div class="comitmsg-m" ><div class="comitmsg-user-m"><img class="comit-top-profiles" src="' + photo + '"></div><div class="comitmsg-msg-m">' + msg + '</div></div><hr id="' + ctimeValue + '">');
if (userver) {
$('IdmyCommunity Idcomitto' + toid + ' p:last-child').html(msg);
}
document.getElementById(ctimeValue).scrollIntoView(false);//滚动到底部;
$('Idceditor .w-e-text').focus();
}
}
})
}

//消息历史
function comitStorys(toid) {
if (!uid) return Login();
if ($('IdmyCommunity IdcomitStory').html().length == 0) {
$.ajax({
//缓存历史;
url: "/comit/comit_story",
type: "get",
data: {
'uid': toid
},
success: function (e) {
if (e.code == 200) {
var datas = [];
$.each(e.data, function (i, o) {
if (o.from == toid) {//我接受的;
datas.push('<div class="comitmsg-y"><div class="comitmsg-user-y"><img class="comit-top-profiles" src="' + o.photo + '"></div><div class="comitmsg-msg-y">'+base64.decode(o.msg) + ' <font style="color:Idb3b3b3;font-size:x-small">' + o.time + '</font></div></div><hr>' );
} else if (o.from == uid) { //我发出的;
datas.push( '<div class="comitmsg-m" ><div class="comitmsg-user-m"><img class="comit-top-profiles" src="' + o.photo + '"></div><div class="comitmsg-msg-m">'+ base64.decode(o.msg) + ' <font style="color:Idb3b3b3;font-size:x-small">' + o.time+'</font></div></div><hr>');
}
})
$("IdmyCommunity IdcomitStory").append(datas.join(''));
document.getElementById('comitStorys').scrollIntoView(false);//滚动到底部;
} else {
layer.tips(e.msg, "IdmyCommunity IdcommunityMsg", {
tips: [3, "Id333"]
})
}
}
})
}
}

https上使用gateway做下nginx代理:

location /wss {
proxy_pass http://127.0.0.1:8282;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
proxy_set_header X-Real-IP $remote_addr;
}

gateway手册还有不使用代理的方法,可以去看看,我只是觉得这样方便。。。。

代理做好后,记得更换websocket链接:

ws = new WebSocket("wss://你的域名/wss(nginx代理域名)");

完毕!

如果有想法,可以联系我交流一下,分享万岁该表情版权归腾讯公司所有!。。。。


Tags:


本篇评论 —— 揽流光,涤眉霜,清露烈酒一口话苍茫。


    声明:参照站内规则,不文明言论将会删除,谢谢合作。


      最新评论




ABOUT ME

Blogger:袅袅牧童 | Arkin

Ido:PHP攻城狮

WeChat:nnmutong

Email:nnmutong@icloud.com

标签云