蝙蝠岛资源网 Design By www.hbtsch.com
Redis 实现每个连接websocket的服务都唯一绑定一个用户。通过 用户账号 = websocket fd 存到redis中。
Mysql 实现离线消息池。如果一个用户不在线,则其他用户发送给他的消息暂时存储在mysql。待该用户上线时,再从离线消息池取出发送。
具体参考代码和相应注释:
<"0.0.0.0", 9052);
$redis = new Redis();
$redis->connect('127.0.0.1', 6379);
$db = new mysqli('127.0.0.1', 'test', 'test', 'thinkphp5');
$server->on('open', function (swoole_websocket_server $server, $request) {
echo "server: handshake success with fd{$request->fd}\n";//$request->fd 是客户端id
});
$server->on('message', function (swoole_websocket_server $server, $frame) {
$data = json_decode($frame->data,true);
if($data['flag'] == 'init'){
//用户刚连接的时候初始化,每个用户登录时记录该用户对应的fd
$GLOBALS['redis']->set($data['from'], $frame->fd);
//处理发给该用户的离线消息
$sql = "SELECT `from`,content FROM thinkphp5.app_offline WHERE `to`='{$data['from']}' AND `from`='{$data['to']}' AND `status`='0' ORDER BY addtime ASC;";
if ($result = $GLOBALS['db']->query($sql)) {
$re = array();
while ($row = $result->fetch_assoc()) {
array_push($re, $row);
}
$result->free();
foreach($re as $content){
$content = json_encode($content);
$server->push($frame->fd , $content);
}
//设置消息池中的消息为已发送
$sql = "UPDATE thinkphp5.app_offline SET `status`=1 WHERE `to`='{$data['from']}' AND `from`='{$data['to']}';";
$GLOBALS['db']->query($sql);
}
}else if($data['flag'] == 'msg'){
//非初始化的信息发送,一对一聊天,根据每个用户对应的fd发给特定用户
$tofd = $GLOBALS['redis']->get($data['to']); //消息要发给谁
$fds = []; //所有在线的用户(打开聊天窗口的用户)
foreach($server->connections as $fd){
array_push($fds, $fd);
}
if(in_array($tofd,$fds)){
$tmp['from'] = $data['from']; //消息来自于谁
$tmp['content'] = $data['content']; //消息内容
$re = json_encode($tmp);
$server->push($tofd , $re);
}else{
//该玩家不在线(不在聊天室内),将信息发送到离线消息池
$time = time();
$sql = "INSERT INTO thinkphp5.app_offline (`to`,`from`,`content`,`status`,`addtime`) VALUES ('{$data['to']}','{$data['from']}','{$data['content']}','0','{$time}');";
$GLOBALS['db']->query($sql);
}
}else if($data['flag'] == 'group'){
//todo 群聊
}else if($data['flag'] == 'all'){
//全站广播
foreach($server->connections as $fd){
$server->push($fd , $data);
}
}
});
$server->on('close', function ($ser, $fd) {
echo "client {$fd} closed\n";
});
$server->start();
客户端代码:
<!DOCTYPE html>
<html>
<head>
<title>XST-app</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=EmulateIE7" />
<meta name="viewport" content="width=device-width, initial-scale=0.0, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0" />
<meta name="keywords" content="test" />
<meta name="description" content="test" />
<meta name="author" content="XST-APP" />
<meta content="yes" name="apple-mobile-web-app-capable" />
<meta content="black" name="apple-mobile-web-app-status-bar-style" />
<meta content="telephone=no" name="format-detection" />
<style type="text/css">
body{background:url(/static/images/yuyin_bg.jpg);background-size:100%;}
@media all and (min-width: 640px) {
body,html,.wenwen-footer,.speak_window{width:640px!important;margin:0 auto}
.speak_window,.wenwen-footer{left:50%!important;margin-left:-320px}
}
input,button{outline:none;}
.wenwen-footer{width:100%;position:fixed;bottom:-5px;left:0;background:#fff;padding:3%;border-top:solid 1px #ddd;box-sizing:border-box;}
.wenwen_btn,.wenwen_help{width:15%;text-align:center;}
.wenwen_btn img,.wenwen_help img{height:40px;}
.wenwen_text{height:40px;border-radius:5px;border:solid 1px #636162;box-sizing:border-box;width:66%;text-align:center;overflow:hidden;margin-left:2%;}
.circle-button{padding:0 5px;}
.wenwen_text .circle-button{font-size:14px;color:#666;line-height:38px;}
.write_box{background:#fff;width:100%;height:40px;line-height:40px;}
.write_box input{height:40px;padding:0 5px;line-height:40px;width:100%;box-sizing:border-box;border:0;}
.wenwen_help button{width:95%;background:#42929d;color:#fff;border-radius:5px;border:0;height:40px;}
#wenwen{height:100%;}
.speak_window{overflow-y:scroll;height:100%;width:100%;position:fixed;top:50px;left:0;}
.speak_box{margin-bottom:70px;padding:10px;}
.question,.answer{margin-bottom:1rem;}
.question{text-align:right;}
.question>div{display:inline-block;}
.left{float:left;}
.right{float:right;}
.clear{clear:both;}
.heard_img{height:60px;width:60px;border-radius:5px;overflow:hidden;background:#ddd;}
.heard_img img{width:100%;height:100%}
.question_text,.answer_text{box-sizing:border-box;position:relative;display:table-cell;min-height:60px;}
.question_text{padding-right:20px;}
.answer_text{padding-left:20px;}
.question_text p,.answer_text p{border-radius:10px;padding:.5rem;margin:0;font-size:14px;line-height:28px;box-sizing:border-box;vertical-align:middle;display:table-cell;height:30px;word-wrap:break-word;}
.answer_text p{background:#fff;}
.question_text p{background:#42929d;color:#fff;text-align:left;}
.question_text i,.answer_text i{width:0;height:0;border-top:5px solid transparent;border-bottom:5px solid transparent;position:absolute;top:25px;}
.answer_text i{border-right:10px solid #fff;left:10px;}
.question_text i{border-left:10px solid #42929d;right:10px;}
.answer_text p a{color:#42929d;display:inline-block;}
.write_list{position:absolute;left:0;width:100%;background:#fff;border-top:solid 1px #ddd;padding:5px;line-height:30px;}
</style>
</head>
<body>
<div id="header" class="head">
<div class="wrap">
<i class="menu_back"><a href="javascript:history.go(-1);" rel="external nofollow" ></a></i>
<div class="title">
<span class="title_d"><p>与 {$tonickname} 的聊天</p></span>
<div class="clear"></div>
</div>
<!--i class="menu_share"></i-->
</div>
</div>
<input type="hidden" name="myemail" id="myemail" value="{$myemail}" />
<input type="hidden" name="mynickname" id="mynickname" value="{$mynickname}" />
<input type="hidden" name="myavatar" id="myavatar" value="{$myavatar}" />
<input type="hidden" name="toemail" id="toemail" value="{$toemail}" />
<input type="hidden" name="tonickname" id="tonickname" value="{$tonickname}" />
<input type="hidden" name="toavatar" id="toavatar" value="{$toavatar}" />
<!-- 对话内容 -->
<div class="speak_window">
<div class="speak_box">
</div>
</div>
<!-- 内容输入-->
<div class="wenwen-footer">
<div class="wenwen_btn left"><img src="/UploadFiles/2021-04-02/jp_btn.png">
数据表结构:
CREATE TABLE `app_offline` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`from` varchar(50) DEFAULT NULL COMMENT '离线发送方',
`to` varchar(50) DEFAULT NULL COMMENT '离线接收方',
`content` varchar(1000) DEFAULT NULL COMMENT '发送的离线内容',
`status` tinyint(4) DEFAULT '0' COMMENT '发送状态:0-未发送,1-已发送',
`addtime` int(11) DEFAULT NULL COMMENT '发送方发送时间',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8
具体效果:
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
蝙蝠岛资源网 Design By www.hbtsch.com
广告合作:本站广告合作请联系QQ:858582 申请时备注:广告合作(否则不回)
免责声明:本站文章均来自网站采集或用户投稿,网站不提供任何软件下载或自行开发的软件! 如有用户或公司发现本站内容信息存在侵权行为,请邮件告知! 858582#qq.com
免责声明:本站文章均来自网站采集或用户投稿,网站不提供任何软件下载或自行开发的软件! 如有用户或公司发现本站内容信息存在侵权行为,请邮件告知! 858582#qq.com
蝙蝠岛资源网 Design By www.hbtsch.com
暂无PHP用swoole+websocket和redis实现web一对一聊天的评论...
RTX 5090要首发 性能要翻倍!三星展示GDDR7显存
三星在GTC上展示了专为下一代游戏GPU设计的GDDR7内存。
首次推出的GDDR7内存模块密度为16GB,每个模块容量为2GB。其速度预设为32 Gbps(PAM3),但也可以降至28 Gbps,以提高产量和初始阶段的整体性能和成本效益。
据三星表示,GDDR7内存的能效将提高20%,同时工作电压仅为1.1V,低于标准的1.2V。通过采用更新的封装材料和优化的电路设计,使得在高速运行时的发热量降低,GDDR7的热阻比GDDR6降低了70%。
更新日志
2025年11月01日
2025年11月01日
- 小骆驼-《草原狼2(蓝光CD)》[原抓WAV+CUE]
- 群星《欢迎来到我身边 电影原声专辑》[320K/MP3][105.02MB]
- 群星《欢迎来到我身边 电影原声专辑》[FLAC/分轨][480.9MB]
- 雷婷《梦里蓝天HQⅡ》 2023头版限量编号低速原抓[WAV+CUE][463M]
- 群星《2024好听新歌42》AI调整音效【WAV分轨】
- 王思雨-《思念陪着鸿雁飞》WAV
- 王思雨《喜马拉雅HQ》头版限量编号[WAV+CUE]
- 李健《无时无刻》[WAV+CUE][590M]
- 陈奕迅《酝酿》[WAV分轨][502M]
- 卓依婷《化蝶》2CD[WAV+CUE][1.1G]
- 群星《吉他王(黑胶CD)》[WAV+CUE]
- 齐秦《穿乐(穿越)》[WAV+CUE]
- 发烧珍品《数位CD音响测试-动向效果(九)》【WAV+CUE】
- 邝美云《邝美云精装歌集》[DSF][1.6G]
- 吕方《爱一回伤一回》[WAV+CUE][454M]
