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. Mac环境下的mongodb的安装

    1.安装MongoDB brew install mongodb 这个是默认安装最新版本的 mogodb,如果想安装指定版本可以先查看 mongodb 版本 brew search mongodb m ...

  2. JavaWeb - Apache与Tomcat有什么关系和区别

    总结: 1- apache是web服务器,侧重于http server: tomcat是应用(java)服务器,侧重于servlet引擎 2-合作过程详解,请看:JavaWeb - apache和to ...

  3. PHP 【四】

    数组 $string = array(x,y,z); <?php$cars=array("Volvo","BMW","Toyota") ...

  4. Dos.Common

    引言: Dos.Common是一个开发中的常用类库,如HttpHelper.LogHelper.CacheHelper.CookieHelper.MapperHelper等等.与Dos.WeChat. ...

  5. installshield安装包制作

    入门教程:http://blog.csdn.net/gaofang2009/article/details/5260065 入门教程:http://blog.csdn.net/plfl520/arti ...

  6. 【原创】大数据基础之Zookeeper(1)介绍、安装及使用

    zookeeper3.4.11 http://zookeeper.apache.org/ 一 简介 ZooKeeper is a centralized service for maintaining ...

  7. 【原创】Linux基础之linux常用命令之文本替换

    linux常用命令之文本替换 1 vi vi test_file :%s/h/h1/g 注释:全文替换,将h替换为h1 :1,4s/h/h1/g 注释:将第1行到第4行的h替换为h1 :%s/\n/, ...

  8. echarts tree 树型图层级距离设置

    网上找了半天,没有找到设置层级距离的属性,默认是自动适应的,无奈只能改源码,分享出来希望可以帮到有相同需求的... 上github下载echarts源码包,打开src=>chart=>tr ...

  9. Visual Studio 2013 突然不高亮,编译报错

    同事的电脑,估计是windows更新失败的原因,C盘容量减小到不到1G,VS的高亮也坏了,重启后硬盘容量增加了但是仍然不高亮. 解决办法记录一下: 重置下. 开始菜单 -->所有程序--> ...

  10. P2921 [USACO08DEC]在农场万圣节Trick or Treat on the Farm 记忆化搜索dfs

    题目描述 每年,在威斯康星州,奶牛们都会穿上衣服,收集农夫约翰在N(1<=N<=100,000)个牛棚隔间中留下的糖果,以此来庆祝美国秋天的万圣节. 由于牛棚不太大,FJ通过指定奶牛必须遵 ...