PHP 简易聊天室 利用redis的订阅发布功能
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的订阅发布功能的更多相关文章
- Express+Socket.IO 实现简易聊天室
代码地址如下:http://www.demodashi.com/demo/12477.html 闲暇之余研究了一下 Socket.io,搭建了一个简易版的聊天室,如有不对之处还望指正,先上效果图: 首 ...
- php_D3_“简易聊天室 ”实现的关键技术 详解
PHP+MySQL实现Internet上一个简易聊天室的关键技术 系统目标: 聊天室使用数据库汇集每个人的发言,并可将数据库内的发言信息显示在页面,让每个用户都可 ...
- 基于Node.js + WebSocket 的简易聊天室
代码地址如下:http://www.demodashi.com/demo/13282.html Node.js聊天室运行说明 Node.js的本质就是运行在服务端的JavaScript.Node.js ...
- Laravel + Swoole 打造IM简易聊天室
最近在学习Swoole,利用Swoole扩展让PHP生动了不少,本篇就来Swoole开发一款简易的IM聊天室 应用场景:实现简单的即时消息聊天室. (一)扩展安装 pecl install swool ...
- php+websocket搭建简易聊天室实践
1.前言 公司游戏里面有个简单的聊天室,了解了之后才知道是node+websocket做的,想想php也来做个简单的聊天室.于是搜集各种资料看文档.找实例自己也写了个简单的聊天室. http连接分为短 ...
- node.js+websocket实现简易聊天室
(文章是从我的个人主页上粘贴过来的,大家也可以访问我的主页 www.iwangzheng.com) websocket提供了一种全双工客户端服务器的异步通信方法,这种通信方法使用ws或者wss协议,可 ...
- Python开发【笔记】:aiohttp搭建简易聊天室
简易聊天室: 1.入口main.py import logging import jinja2 import aiohttp_jinja2 from aiohttp import web from a ...
- 学习JavaSE TCP/IP协议与搭建简易聊天室
一.TCP/IP协议 1.TCP/IP协议包括TCP.IP和UDP等 2.域名通过dns服务器转换为IP地址 3.局域网可以通过IP或者主机地址寻找到相应的主机 4.TCP是可靠的连接,效率低,且连接 ...
- 示例:Socket应用之简易聊天室
在实际应用中,Server总是在指定的端口上监听是否有Client请求,一旦监听到Client请求,Server就会启动一个线程来响应该请求,而Server本身在启动完线程之后马上又进入监听状态. 示 ...
随机推荐
- Spring扩展自定义的XML标签
在网上搜了许多,感觉不够全面,就找了官方文档,下面记录如何找到对应的文档进入 网上许多博客都是以dateformat为实例进行编写的,通过官方的foo,能够学到更多的东西,下面贴一段代码,在官方示例上 ...
- Laravel 生成migration ,boolean字段字段转为tinyInteger
Schema::create('consults', function (Blueprint $table) { $table->increments('id'); $table->str ...
- 【原创】大叔问题定位分享(11)Spark中对大表子查询加limit为什么会报Broadcast超时错误
当两个表需要join时,如果一个是大表,一个是小表,正常的map-reduce流程需要shuffle,这会导致大表数据在节点间网络传输,常见的优化方式是将小表读到内存中并广播到大表处理,避免shuff ...
- JavaScript入门(基础)
一.JS语言介绍 1.概述 浏览器脚本语言 可以编写运行在浏览器上的代码程序 属于解释性.弱语言类型编程语言 2.组成 ES语法:ECMAScript.主要版本有ES5和ES6 DOM:文档对象模型( ...
- 12、Grafan 4.3升级到Grafana 5.0
Upgrading Grafana 升级Grafana We recommend everyone to upgrade Grafana often to stay up to date with t ...
- leetcode目录
Leetcode 1. 数组 2. 动态规划 3. 字符串 4. 链表.双指针.排序 5. 树 6. 回溯算法.贪心算法.分治算法.
- Codeforces 1097E. Egor and an RPG game 构造
原文链接https://www.cnblogs.com/zhouzhendong/p/CF1097E.html 题解 首先我们求出 $k = f(n) = \max\{x|\frac{x(x+1)}2 ...
- SSH项目需要的所有架包
原地址:https://blog.csdn.net/qq_35816104/article/details/54346182 SSH框架:struts2 hibernate spring 该三大框 ...
- Linux 添加到环境变量
在Linux下使用源码安装软件的时候,通常只能在软件安装目录下使用该软件命令,这样太麻烦,我们希望全局使用,可以将软件安装路径添加到系统环境变量里. 添加环境变量有2种方法: 1. 使用export命 ...
- Selenium获取当前窗口句柄与切换回原窗口句柄
Selenium通过window_handles获取当前窗口句柄,进行页面元素操作 切换回原窗口句柄,进行元素操作 代码如下:(python版) __author__ = 'liuke' import ...