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. 使用Cobbler批量部署Linux和Windows:Windows系统批量安装(三)

    Tutorial: Installing Windows with cobbler (cobbler安装Windows) Windows系统的自动安装需要用到Win PE工具.流程如下: 定制Win ...

  2. 51nod 1035 最长的循环节

    正整数k的倒数1/k,写为10进制的小数如果为无限循环小数,则存在一个循环节,求<=n的数中,倒数循环节长度最长的那个数,假如存在多个最优的答案,输出所有答案中最大的那个数. 1/6= 0.1( ...

  3. 华为mate10 UA

    Dalvik/2.1.0 (Linux; U; Android 9; ALP-AL00 Build/HUAWEIALP-AL00) "user-agent": "Mozi ...

  4. Apache JMeter压力测试实例

    脚本录制 脚本录制,JMeter启用WEB代理,浏览器把代理上网设置为JMeter所在的IP地址,自己电脑就是127.0.0.1代理端口默认8080.至于浏览器修改代理上网服务器,不做截图. Jmet ...

  5. WPF 单个触发器、多个触发器、多条件触发器

    Trigger的使用.利用Trigger对象,我们可以接收到属性变化或者事件发生,并据此做出适当的响应.Trigger本身也是支持多种类型的,下面是一个属性Trigger的例子: <Style ...

  6. JavaScript入门学习笔记(JSON)

    JSON是JavaScript Object Notation的简称,是一种轻量级的数据交换格式. JSON使用JS的语法,但其格式只是一个文本,可以被任何编程语言读取病作为数据格式传递. JSON以 ...

  7. Niagara workbench (Basic )

    1.the basic information about workbench Last saved  station open in the workbench or opened  another ...

  8. Knockout中ko.utils中处理数组的方法集合

    每一套框架基本上都会有一个工具类,如:Vue中的Vue.util.Knockout中的ko.utils.jQuery直接将一些工具类放到了$里面,如果你还需要更多的工具类可以试试lodash.本文只介 ...

  9. git 回滚远程服务端master的代码

    1.先备份版本 git checkout master git pull git branch master_backup //备份一下这个分支当前的情况 git push origin master ...

  10. 原子动作检测 A Better Baseline for AVA

    本文将Faster-RCNN用在了I3D的feature map上,用于视频中多人多动作的检测 challege比赛第二名的整体方法是将Faster-RCNN作用在I3Dfeature上.训练时,以标 ...