demo:
http://139.196.97.20:8083/api/chat/list

前言:
这个种方式太耗redis连接数,每次订阅都会新起一个进程,仅供练手使用,切勿用于生产环境。

原理:
1.PHP提供两个接口,订阅,发布,redis就有提供
2.订阅接口会卡住,不会马上response,直至有发布的消息
3.前端需要在一次订阅请求成功或失败后立即重新发一个订阅请求,以免错漏信息

后台代码(用的laravel框架,只要能调用redis,实现一致即可):

// 订阅接口
public function subscribe(Request $request)
{
Redis::subscribe([self::CHATROOMCHANNEL], function ($message) {
echo json_encode($this->rtnSucc($message));
exit;
});
}

// 发布接口
public function publish(Request $request)
{
$num = Redis::publish(self::CHATROOMCHANNEL, $request->input('say', '对方没有说话'));
if ($num) {
return $this->rtnSucc($num);
} else {
return $this->rtnErr(100, "发送失败");
}
} private function rtnSucc($data)
{
return ["rtn" => 0, "msg" => "", "data" => $data];
} private function rtnErr($rtn, $msg = "")
{
return ["rtn" => $rtn, "msg" => $msg, "data" => ""];
}

前端代码:

<!DOCTYPE html>
<html lang="zh">
<head>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>200OK ChatRoom</title>
<style>
body {
margin: 0;
padding: 0;
} #input_box {
width: 92%;
height: 100px;
margin: 0 auto;
display: block;
border-radius: 2px;
} #btn {
height: 30px;
text-align: center;
font-size: 16px;
background-color: #E91E63;
color: #fff;
margin: 10px 10px 0 10px;
border-radius: 2px;
line-height: 30px;
} #content {
margin: 0 10px;
font-size: 16px;
color: #795548;
}
</style>
</head>
<body> <div id="content">
<p>200 OK ChatRoom!</p>
</div>
<textarea id="input_box" placeholder="输入你想说的话"></textarea>
<div id="btn">发射!</div>
<script src="/js/zepto.js"></script>
<script src="/js/md5.min.js"></script>
<script>
// dom
let $input_box = $("#input_box");
let $content = $("#content");
let $btn = $("#btn");
let myName = getRandomName(); main(); // 入口
function main() {
bindEvent();
subscribe();
$content.append(pp("你叫:" + myName));
} // 监听事件
function bindEvent() {
$btn.on("click", function () {
say();
}); $input_box.bind('keyup', function (e) {
if (13 === e.keyCode) {
say();
}
});
} // 说
function say() {
var str = getC().trim();
if (!str) {
error("请输入内容");
return;
}
publish(namePrefix() + str, function (rp) {
$input_box.val("");
$input_box.focus();
});
} // 获取输入框内容
function getC() {
return $input_box.val();
} // 订阅 回调之后继续订阅
function subscribe(callback) {
$.ajax({
type: 'GET',
url: '/api/chat/subscribe',
data: {},
dataType: 'json',
timeout: 10000,
success: function (data) {
if (0 === data.rtn) {
$content.append(pp(data.data));
}
subscribe();
},
error: function (xhr, type) {
// 防止雪崩
setTimeout(function () {
subscribe();
}, 1000);
}
});
} // 发布
function publish(str, callback) {
$.get('/api/chat/publish?say=' + str, function (response) {
callback(response);
});
} function pp(str) {
return "<p>" + str + "</p>"
} function namePrefix() {
return myName + ": ";
} // 错误处理
function error(str) {
alert(str);
} // 生成随机姓名
function getRandomName() {
var familyNames = new Array(
"赵", "钱", "孙", "李", "周", "吴", "郑", "王", "冯", "陈",
"褚", "卫", "蒋", "沈", "韩", "杨", "朱", "秦", "尤", "许",
"何", "吕", "施", "张", "孔", "曹", "严", "华", "金", "魏",
"陶", "姜", "戚", "谢", "邹", "喻", "柏", "水", "窦", "章",
"云", "苏", "潘", "葛", "奚", "范", "彭", "郎", "鲁", "韦",
"昌", "马", "苗", "凤", "花", "方", "俞", "任", "袁", "柳",
"酆", "鲍", "史", "唐", "费", "廉", "岑", "薛", "雷", "贺",
"倪", "汤", "滕", "殷", "罗", "毕", "郝", "邬", "安", "常",
"乐", "于", "时", "傅", "皮", "卞", "齐", "康", "伍", "余",
"元", "卜", "顾", "孟", "平", "黄", "和", "穆", "萧", "尹"
);
var givenNames = new Array(
"子璇", "淼", "国栋", "夫子", "瑞堂", "甜", "敏", "尚", "国贤", "贺祥", "晨涛",
"昊轩", "易轩", "益辰", "益帆", "益冉", "瑾春", "瑾昆", "春齐", "杨", "文昊",
"东东", "雄霖", "浩晨", "熙涵", "溶溶", "冰枫", "欣欣", "宜豪", "欣慧", "建政",
"美欣", "淑慧", "文轩", "文杰", "欣源", "忠林", "榕润", "欣汝", "慧嘉", "新建",
"建林", "亦菲", "林", "冰洁", "佳欣", "涵涵", "禹辰", "淳美", "泽惠", "伟洋",
"涵越", "润丽", "翔", "淑华", "晶莹", "凌晶", "苒溪", "雨涵", "嘉怡", "佳毅",
"子辰", "佳琪", "紫轩", "瑞辰", "昕蕊", "萌", "明远", "欣宜", "泽远", "欣怡",
"佳怡", "佳惠", "晨茜", "晨璐", "运昊", "汝鑫", "淑君", "晶滢", "润莎", "榕汕",
"佳钰", "佳玉", "晓庆", "一鸣", "语晨", "添池", "添昊", "雨泽", "雅晗", "雅涵",
"清妍", "诗悦", "嘉乐", "晨涵", "天赫", "玥傲", "佳昊", "天昊", "萌萌", "若萌"
); var i = parseInt(10 * Math.random()) * 10 + parseInt(10 * Math.random());
var familyName = familyNames[i]; var j = parseInt(10 * Math.random()) * 10 + parseInt(10 * Math.random());
var givenName = givenNames[i]; return familyName + givenName;
}
</script>
</body>
</html>

PHP 简易聊天室 利用redis的订阅发布功能的更多相关文章

  1. Express+Socket.IO 实现简易聊天室

    代码地址如下:http://www.demodashi.com/demo/12477.html 闲暇之余研究了一下 Socket.io,搭建了一个简易版的聊天室,如有不对之处还望指正,先上效果图: 首 ...

  2. php_D3_“简易聊天室 ”实现的关键技术 详解

                      PHP+MySQL实现Internet上一个简易聊天室的关键技术  系统目标: 聊天室使用数据库汇集每个人的发言,并可将数据库内的发言信息显示在页面,让每个用户都可 ...

  3. 基于Node.js + WebSocket 的简易聊天室

    代码地址如下:http://www.demodashi.com/demo/13282.html Node.js聊天室运行说明 Node.js的本质就是运行在服务端的JavaScript.Node.js ...

  4. Laravel + Swoole 打造IM简易聊天室

    最近在学习Swoole,利用Swoole扩展让PHP生动了不少,本篇就来Swoole开发一款简易的IM聊天室 应用场景:实现简单的即时消息聊天室. (一)扩展安装 pecl install swool ...

  5. php+websocket搭建简易聊天室实践

    1.前言 公司游戏里面有个简单的聊天室,了解了之后才知道是node+websocket做的,想想php也来做个简单的聊天室.于是搜集各种资料看文档.找实例自己也写了个简单的聊天室. http连接分为短 ...

  6. node.js+websocket实现简易聊天室

    (文章是从我的个人主页上粘贴过来的,大家也可以访问我的主页 www.iwangzheng.com) websocket提供了一种全双工客户端服务器的异步通信方法,这种通信方法使用ws或者wss协议,可 ...

  7. Python开发【笔记】:aiohttp搭建简易聊天室

    简易聊天室: 1.入口main.py import logging import jinja2 import aiohttp_jinja2 from aiohttp import web from a ...

  8. 学习JavaSE TCP/IP协议与搭建简易聊天室

    一.TCP/IP协议 1.TCP/IP协议包括TCP.IP和UDP等 2.域名通过dns服务器转换为IP地址 3.局域网可以通过IP或者主机地址寻找到相应的主机 4.TCP是可靠的连接,效率低,且连接 ...

  9. 示例:Socket应用之简易聊天室

    在实际应用中,Server总是在指定的端口上监听是否有Client请求,一旦监听到Client请求,Server就会启动一个线程来响应该请求,而Server本身在启动完线程之后马上又进入监听状态. 示 ...

随机推荐

  1. 「luogu2486」[SDOI2011] 染色

    https://www.luogu.org/problemnew/show/P2486 轻重链剖分后,问题转化为一个链上的问题: 线段树维护区间内的颜色段数量,左端点.右端点的颜色: 线段树注意事项 ...

  2. 题解-HNOI2017 抛硬币

    Problem loj2023 题意概述:甲抛掷 \(a\) 次硬币,乙抛掷 \(b\) 次硬币,问有多少种情况甲正面向上的次数比乙多,答案对 \(10^k\) 取模 对于 \(10\%\) 的数据, ...

  3. springboot配置详解

    springboot配置详解 Author:SimpleWu properteis文件属性参考大全 springboot默认加载配置 SpringBoot使用两种全局的配置文件,全局配置文件可以对一些 ...

  4. 九.LNMP网站架构实践部署

    期中集群架构-第九章-期中架构LNMP章节====================================================================== 01. LNMP ...

  5. Vulnerability Scanning

    1.Vulnerability scanning with Nmap Scripting Engine the Nmap Script Engine provide a alrge number of ...

  6. C# .Net 中字典Dictionary<TKey,TValue>泛型类 学习浅谈

    一.综述: Dictionary<TKey,TValue>是在 .NET Framework 2.0 版中是新增的.表示键值对的集合,Dictionary<TKey,TValue&g ...

  7. [转] 如何写好.babelrc?Babel的presets和plugins配置解析

    什么是Babel The compiler for writing next generation JavaScript. 官网是这么说的,翻译一下就是下一代JavaScript 语法的编译器. 作为 ...

  8. [C#.Net]全局钩子实现USB扫码枪无焦点状态下扫入

    https://www.cnblogs.com/masonlu/p/10105135.html

  9. 一键配置高可用Hadoop集群(hdfs HA+zookeeper HA)

    准备环境 3台节点,主节点 建议 2G 内存,两个从节点 1.5G内存, 桥接网络 关闭防火墙 配置ssh,让节点之间能够相互 ping 通 准备  软件放到 autoInstall  目录下,已存放 ...

  10. Ubuntu16.04 将其他磁盘挂载到 /home, 解决/home空间不足

    本文转载自: https://blog.csdn.net/handsome_for_kill/article/details/52654724 1.查看磁盘信息 sudo fdisk -l 查看分区的 ...