1. <?php
  2. ini_set('display_errors', 'on');
  3.  
  4. class chatClass {
  5. private $redis;
  6.  
  7. //这个变量模拟用户当前状态,是否登录,是否可查看
  8. public $checkUserReadable = false;
  9.  
  10. //构造函数链接redis数据库
  11. public function __construct() {
  12. $this -> redis = new Redis();
  13. $this -> redis -> connect('127.0.0.1', '6379');
  14. $this -> redis -> auth('***cnblogs.com/handle');
  15. }
  16.  
  17. /*
  18. 发送消息时保存聊天记录
  19. * 这里用的redis存储是list数据类型
  20. * 两个人的聊天用一个list保存
  21. *
  22. * @from 消息发送者id
  23. * @to 消息接受者id
  24. * @meassage 消息内容
  25. *
  26. * 返回值,当前聊天的总聊天记录数
  27. */
  28. public function setChatRecord($from, $to, $message) {
  29. $data = array('from' => $from, 'to' => $to, 'message' => $message, 'sent' => time()/*, 'recd' => 0*/);
  30. $value = json_encode($data);
  31. //生成json字符串
  32. $keyName = 'rec:' . $this -> getRecKeyName($from, $to);
  33. //echo $keyName;
  34. $res = $this -> redis -> lPush($keyName, $value);
  35. if (!$this -> checkUserReadable) {//消息接受者无法立刻查看时,将消息设置为未读
  36. $this -> cacheUnreadMsg($from, $to);
  37. }
  38. return $res;
  39. }
  40.  
  41. /*
  42. * 获取聊天记录
  43. * @from 消息发送者id
  44. * @to 消息接受者id
  45. * @num 获取的数量
  46. *
  47. * 返回值,指定长度的包含聊天记录的数组
  48. */
  49. public function getChatRecord($from, $to, $num) {
  50. $keyName = 'rec:' . $this -> getRecKeyName($from, $to);
  51. //echo $keyName;
  52. $recList = $this -> redis -> lRange($keyName, 0, (int)($num));
  53. return $recList;
  54. }
  55.  
  56. /*
  57. * 当用户上线时,或点开聊天框时,获取未读消息的数目
  58. * @user 用户id
  59. *
  60. * 返回值,一个所有当前用户未读的消息的发送者和数组
  61. * 数组格式为‘消息发送者id’=>‘未读消息数目’
  62. *
  63. */
  64. public function getUnreadMsgCount($user) {
  65. return $this -> redis -> hGetAll('unread_' . $user);
  66. }
  67.  
  68. /*
  69. * 获取未读消息的内容
  70. * 通过未读消息数目,在列表中取得最新的相应消息即为未读
  71. * @from 消息发送者id
  72. * @to 消息接受者id
  73. *
  74. * 返回值,包括所有未读消息内容的数组
  75. *
  76. *
  77. */
  78. public function getUnreadMsg($from, $to) {
  79. $countArr = $this -> getUnreadMsgCount($to);
  80. $count = $countArr[$from];
  81. $keyName = 'rec:' . $this -> getRecKeyName($from, $to);
  82. return $this -> redis -> lRange($keyName, 0, (int)($count));
  83. }
  84.  
  85. /*
  86. * 将消息设为已读
  87. * 当一个用户打开另一个用户的聊天框时,将所有未读消息设为已读
  88. * 清楚未读消息中的缓存
  89. * @from 消息发送者id
  90. * @to 消息接受者id
  91. *
  92. * 返回值,成功将未读消息设为已读则返回true,没有未读消息则返回false
  93. */
  94.  
  95. public function setUnreadToRead($from, $to) {
  96. $res = $this -> redis -> hDel('unread_' . $to, $from);
  97. return (bool)$res;
  98. }
  99.  
  100. /*
  101. * 当用户不在线时,或者当前没有立刻接收消息时,缓存未读消息,将未读消息的数目和发送者信息存到一个与接受者关联的hash数据中
  102. *
  103. * @from 发送消息的用户id
  104. * @to 接收消息的用户id
  105. *
  106. * 返回值,当前两个用户聊天中的未读消息
  107. *
  108. */
  109. private function cacheUnreadMsg($from, $to) {
  110. return $this -> redis -> hIncrBy('unread_' . $to, $from, 1);
  111. }
  112.  
  113. /*生成聊天记录的键名,即按大小规则将两个数字排序
  114. * @from 消息发送者id
  115. * @to 消息接受者id
  116. *
  117. *
  118. */
  119. private function getRecKeyName($from, $to) {
  120. return ($from > $to) ? $to . '_' . $from : $from . '_' . $to;
  121. }
  122.  
  123. }
  124.  
  125. /*
  126. * 下面为测试用的代码 ,伪造数据模拟场景
  127. * 假定有两个用户id为2和3 ,2 向 3 发送消息
  128. *
  129.  
  130. $chat = new chatClass();
  131.  
  132. $chat -> checkUserReadable = true;
  133. for ($i = 0; $i < 20; $i++) {
  134. $chat -> setChatRecord('2', '3', 'message_' . $i);
  135. }
  136.  
  137. echo 'get 20 chat records</br>';
  138. $arr = $chat -> getChatRecord('2', '3', 20);
  139. for ($j = 0; $j < count($arr); $j++) {
  140. echo $arr[$j] . '</br>';
  141. }
  142.  
  143. $chat -> checkUserReadable = false;
  144.  
  145. for ($m = 0; $m < 5; $m++) {
  146. $chat -> setChatRecord('2', '3', 'message_' . $m);
  147. }
  148.  
  149. echo "</br>";
  150. $umsg_1 = $chat -> getUnreadMsgCount(3);
  151. echo "Unread message counts ";
  152. echo "</br>";
  153. print_r($umsg_1);
  154. echo "Unread message content </br> ";
  155. $umsgContent = $chat -> getUnreadMsg(2, 3);
  156. for ($n = 0; $n < count($umsgContent); $n++) {
  157. echo $arr[$n] . '</br>';
  158. }
  159. echo "</br>";
  160. $chat -> setUnreadToRead(2, 3);
  161. $umsg_2 = $chat -> getUnreadMsgCount(3);
  162. echo "</br>";
  163. echo "Unread message counts ";
  164. echo "</br>";
  165. print_r($umsg_2);
  166. *
  167. */
  168. ?>

php redis 处理websocket聊天记录的更多相关文章

  1. Canvas + WebSocket + Redis 实现一个视频弹幕

    原文出自:https://www.pandashen.com 页面布局 首先,我们需要实现页面布局,在根目录创建 index.html 布局中我们需要有一个 video 多媒体标签引入我们的本地视频, ...

  2. Swoole Redis 连接池的实现

    概述 这是关于 Swoole 入门学习的第九篇文章:Swoole Redis 连接池的实现. 第八篇:Swoole MySQL 连接池的实现 第七篇:Swoole RPC 的实现 第六篇:Swoole ...

  3. Spring Boot 2.x 系列教程:WebFlux 系列教程大纲(一)

    摘要: 原创出处 https://www.bysocket.com 「公众号:泥瓦匠BYSocket 」欢迎关注和转载,保留摘要,谢谢! WebFlux 系列教程大纲 一.背景 大家都知道,Sprin ...

  4. laravel 事件广播

    Laravel 5.1 之中新加入了事件广播的功能,作用是把服务器中触发的事件通过websocket服务通知客户端,也就是浏览器,客户端js根据接受到的事件,做出相应动作.本文会用简单的代码展示一个事 ...

  5. Laravel 中使用 swoole 项目实战开发案例一 (建立 swoole 和前端通信)

    1 开发需要环境 工欲善其事,必先利其器.在正式开发之前我们检查好需要安装的拓展,不要开发中发现这些问题,打断思路影响我们的开发效率. 安装 swoole 拓展包 安装 redis 拓展包 安装 la ...

  6. Laravel 中使用 swoole 项目实战开发案例二 (后端主动分场景给界面推送消息)

    推荐阅读:Laravel 中使用 swoole 项目实战开发案例一 (建立 swoole 和前端通信)​ 需求分析 我们假设有一个需求,我在后端点击按钮 1,首页弹出 “后端触发了按钮 1”.后端点了 ...

  7. SpringBoot 和Vue前后端分离入门教程(附源码)

    作者:梁小生0101 juejin.im/post/5c622fb5e51d457f9f2c2381 推荐阅读(点击即可跳转阅读) 1. SpringBoot内容聚合 2. 面试题内容聚合 3. 设计 ...

  8. Spring Boot WebFlux-导读

    背景 大家都知道,Spring Framework 是 Java/Spring 应用程序跨平台开发框架,也是 Java EE(Java Enterprise Edition) 轻量级框架,其 Spri ...

  9. 脚踏实地的Netty源码研究笔记——开篇

    1. 脚踏实地的Netty源码研究笔记--开篇 1.1. Netty介绍 Netty是一个老牌的高性能网络框架.在众多开源框架中都有它的身影,比如:grpc.dubbo.seata等. 里面有着非常多 ...

随机推荐

  1. kerberos环境storm配置:Running Apache Storm Securely

    Running Apache Storm Securely Apache Storm offers a range of configuration options when trying to se ...

  2. [题解] 2038: [2009国家集训队]小Z的袜子(hose)

    莫队,卡常数 题目地址 思路 设\(\text{Vis[i]}\)为元素\(\text{i}\)在区间\(\text{[L,R]}\)的出现次数 考虑区间\(\text{[L,R]}\)和元素\(\t ...

  3. STM32的IAP实现

    STM32的IAP实现 2014年07月28日 16:31:06 Stylesen 阅读数:556   IAP,全称是“In-Application Programming”,中文解释为“在程序中编程 ...

  4. Vue评论组件案例

    最近学习了Vue前端框架,在这里记录一下组件的用法,我自己试着写了一个评论的组件,大神看到勿喷,欢迎提出宝贵意见. 首先看一下效果图 用到的文件有: <link rel="styles ...

  5. Spring之旅第三篇-Spring配置详解

    上一篇学习了IOC的概念并初步分析了实现原理,这篇主要学习Spring的配置,话不多说,让我们开始! 一.Bean元素配置 1.1 基本配置 看一个最基本的bean配置 <bean name=& ...

  6. Python 包构建教程

    目录 setuptools 和 setup.py 你所需要做的事 & 一些概念 基础概念 关于源码分发文件和二进制分发文件 示例和分发选择 pure python module package ...

  7. 【大数据安全】基于Kerberos的大数据安全验证方案

    1.背景 互联网从来就不是一个安全的地方.很多时候我们过分依赖防火墙来解决安全的问题,不幸的是,防火墙是假设"坏人"是来自外部的,而真正具有破坏性的攻击事件都是往往都是来自于内部的 ...

  8. javascript中的typeof和类型判断

    typeof ECMAScript 有 5 种原始类型(primitive type),即 Undefined.Null.Boolean.Number 和 String.我们都知道可以使用typeof ...

  9. InnoSetup 以命令行自动编译打包

    本章介绍,在新建Innosetup的编译脚本iss文件后,在不运行Innosetup软件的基础上,以bat自动编译运行打包. 一.添加Innosetup软件包 下载InnoSetup软件包并解压到bu ...

  10. python 自定义模块的发布和安装

    [学习笔记] 自定义模块 使用的是pycharm 说白了就是.py文件都可以作为模块导入,像定义一个文件 名字为Mycode __all__ = ["add","sub& ...