首页 > 作文

PHP用swoole+websocket和redis实现web一对一聊天

更新时间:2023-04-08 05:57:16 阅读: 评论:0

redis 实现每个连接websocket的服务都唯一绑定一个用户。通过 用户账号 = websocket fd 存到redis中。

mysql 实现离线消息池。如果一个用户不在线,则其他用户发送给他的消息暂时存储在mysql。待该用户上线时,再从离线消息池取出发送。

具体参考代码和相应注释:

<?php$rver = new swoole_websocket_rver("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');$rver->on('open', function (swoole_websocket_rver $rver, $request) { echo "rver: 七年级数学handshake success with fd{$request->fd}\n";//$request->fd 是客户端id});$rver->on('message', function (swoole_websocket_rver $rver, $frame) { $data = json_decode($frame->data,true);  if($data['flag'] == 'init'){  //用户刚连接的时候初始化,每个用户登录时记录该用户对应的fd  $globals['redis']->t($data['from'], $frame->fd);  //处理发给该用户的离线消息  $sql = "lect `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);    $rver->push($frame->fd , $content);   }   //设置消息池中的消息为已发送   $sql = "update thinkphp5.app_offline t `status`=1 where `to`='{$data['from']}' and `from`='{$data['to']}';";   $globals['db']->query($sql); 周日用英语怎么说 } }el if($data['flag'] == 'msg'){  //非初始化的信息发送,一对一聊天,根据每个用户对应的fd发给特定用户  $tofd = $globals['redis']->get($data['to']); //消息要发给谁  $fds = []; //所有在线的用户(打开聊天窗口的用户)  foreach($rver->connections as $fd){   array_push($fds, $fd);  }  if(in_array($tofd,$fds)){   $tmp['from'] = $data['from']; //消息来自于谁   $tmp['content'] = $data['content']; //消息内容   $re = json_encode($tmp);   $rver->push($tofd , $re);o2o模式  }el{   //该玩家不在线(不在聊天室内),将信息发送到离线消息池   $time = time();   $sql = "inrt into thinkphp5.app_offline (`to`,`from`,`content`,`status`,`addtime`) values ('{$data['to']}','{$data['from']}','{$data['content']}','0','{$time}');";   $globals['db']->query($sql);  } }el if($data['flag'] == 'group'){  //todo 群聊   }el if($data['flag'] == 'all'){  //全站广播  foreach($rver->connections as $fd){   $rver->push($fd , $data);  } } });$rver->on('clo', function ($r, $fd) { echo "client {$fd} clod\n";});$rver->start();

客户端代码:

<!doctype html><html><head> <title>xst-app</title> <meta http-equiv="content-type" content="text/html; chart=utf-8" /> <meta http-equiv="x-ua-compatible" content="ie=emulateie7" /> <meta name="viewport" content="width=device-width, initial-scale=0.0, ur-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="/static/images/jp_btn.png"></div> <div class="wenwen_text left">  <div class="write_box"><input type="text" class="left" onkeyup="keyup()" maxlength="100" placeholder="请输入信息(100字以内)..." /></div>  </div> <div class="wenwen_help right">   <button onclick="nd()" class="right">发送</button> </div> <div style="opacity:0;" class="clear"></div></div><script type="text/javascript"> if ("websocket" in window){  var ws = new websocket("ws://192.168.0.1:9052");  ws.onopen = function(){   console.log("握手成功");   var myemail = $("#myemail").val();   var toemail = $("#toemail").val();   var arr = {"flag":"init","from":myemail,"to":toemail};   var str = json.stringify(arr);   ws.nd(str);  };  ws.onmessage = function(e){   var toemail = $("#toemail").val();   var toavatar = $("#toavatar").val();   var obj = json.par(e.data);   console.log(e.data);   //但同时与两个人聊天时,可能两个人的消息都会出现在当前窗口,所以此处加个判断,此窗口只接收当前聊天对象的消息,其他则忽略   if(obj.from === toemail){    var ans = '<div class="answer"><div class="heard_img left"><img src="'+toavatar+'"></div>';     ans += '<div class="answer_text"><p>'+obj.content+'</p><i></i>';     ans += '</div></div>';     $('.speak_box').append(ans);     for_bottom();   }  };  ws.onerror = function(){   console.log("error");   var str = '<div class="question">';   str += '<div class="heard_img right"><img src="/static/images/xitong.jpg"></div>';   str += '<div class="question_text clear"><p>聊天服务器出现异常,暂时无法提供服务。</p><i></i>';   str += '</div></div>';   $('.speak_box').append(str);   $('.write_box input').val('');   $('.write_box input').focus();   autowidth();   for_bottom();  };  function nd() {   var content = $('.write_box input').val();  if(content === ''){   alert('请输入消息!');   $('.write_box input').focus();  }el{    var toemail = $("#toemail").val();    var myemail = $("#myemail").val();    var myavatar = $("#myavatar").val();    var arr = {"flag":"msg","to":toemail,"from":myemail,"content":content};    var msg = json.stringify(arr);    console.log(msg);    ws.nd(msg);     var str = '<div class="question">';    str += '<div class="heard_img right"><img src="'+myavatar+'"></div>';    str += '<div class="question_text clear"><p>'+content+'</p><i></i>';    str += '</div></div>';   $('.speak_box').append(str);   $('.write_box input').val('');   $('.write_box input').focus();   autowidth();   for_bottom();   }    } }el{  alert("您的浏览器不支持 websocket!"); }    function for_bottom(){ var speak_height = $('.speak_box').height(); $('.speak_box,.speak_window').animate({scrolltop:speak_height},500); }  function autowidth(){ $('.question_t云南师范大学录取分数线ext').css('max-width',$('.question').width()-60); }  autowidth(); </script></body></html>

数据表结构:

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 chart=utf8

具体效果:

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持www.887551.com。

本文发布于:2023-04-08 05:57:14,感谢您对本站的认可!

本文链接:https://www.wtabcd.cn/fanwen/zuowen/aba0b3292ff373f1b72073ccadca49b2.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

本文word下载地址:PHP用swoole+websocket和redis实现web一对一聊天.doc

本文 PDF 下载地址:PHP用swoole+websocket和redis实现web一对一聊天.pdf

标签:离线   消息   用户   该用户
相关文章
留言与评论(共有 0 条评论)
   
验证码:
Copyright ©2019-2022 Comsenz Inc.Powered by © 专利检索| 网站地图