PHP框架实现WebSocket在线聊天通讯系统


Posted in PHP onNovember 21, 2019

ThinkPHP使用Swoole需要安装 think-swoole Composer包,前提系统已经安装好了Swoole PECL 拓展

tp5的项目根目录下执行composer命令安装think-swoole:

composer require topthink/think-swoole

话不多说,直接上代码:

新建WebSocket.php控制器:

(监听端口要确认服务器放行,宝塔环境还需要添加安全组规则)

<?php
namespace app\home\controller;
use think\swoole\Server;
class WebSocket extends Server
{
 protected $host = '0.0.0.0'; //监听所有地址
 protected $port = 9501; //监听9501端口
 protected $serverType = 'socket';
 protected $option = [ 
  'worker_num'=> 4, //设置启动的Worker进程数
  'daemonize' => false, //守护进程化(上线改为true)
  'backlog' => 128, //Listen队列长度
  'dispatch_mode' => 2, //固定模式,保证同一个连接发来的数据只会被同一个worker处理
  //心跳检测:每60秒遍历所有连接,强制关闭10分钟内没有向服务器发送任何数据的连接
  'heartbeat_check_interval' => 60,
  'heartbeat_idle_time' => 600
 ];
 //建立连接时回调函数
 public function onOpen($server,$req)
 {
  $fd = $req->fd;//客户端标识
  $uid = $req->get['uid'];//客户端传递的用户id
  $token = $req->get['token'];//客户端传递的用户登录token
  //省略token验证逻辑......
  if (!$token) {
   $arr = array('status'=>2,'message'=>'token已过期');
   $server->push($fd, json_encode($arr));
   $server->close($fd);
   return;
  }
  //省略给用户绑定fd逻辑......
  echo "用户{$uid}建立了连接,标识为{$fd}\n";
 }
 //接收数据时回调函数
 public function onMessage($server,$frame)
 {
  $fd = $frame->fd;
  $message = $frame->data;
  //省略通过fd查询用户uid逻辑......
  $uid = 666;
  $data['uid'] = $uid;
  $data['message'] = '用户'.$uid.'发送了:'.$message;
  $data['post_time'] = date("m/d H:i",time());
  $arr = array('status'=>1,'message'=>'success','data'=>$data);
  //仅推送给当前连接用户
  //$server->push($fd, json_encode($arr));
  //推送给全部连接用户
  foreach($server->connections as $fd) {
   $server->push($fd, json_encode($arr));
  } 
 }
 //连接关闭时回调函数
 public function onClose($server,$fd)
 {
  echo "标识{$fd}关闭了连接\n";
 }
}

前端演示页面:

(省略控制器判断登录状态、分配数据逻辑......)

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
<meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" />
<title>Chat</title>
<link rel="stylesheet" type="text/css" href="/static/liaotian/chat.css" rel="external nofollow" />
<script src="/static/liaotian/js/jquery.min.js"></script>
<script src="/static/liaotian/js/flexible.js"></script>
</head>
<body>
 <header class="header">
  <a class="back" href="javascript:history.back()" rel="external nofollow" ></a>
  <h5 class="tit">在线聊天</h5>
  <a href=""><div class=" rel="external nofollow" right">退出</div></a>
 </header>
 
 <!-- 聊天内容 start-->
 <div class="message"> </div>
 <!-- 聊天内容 end-->
 
 <!-- 底部 start-->
 <div class="footer">
  <img id="setbtn" src="/static/liaotian/images/hua.png" alt="" />
  <img src="/static/liaotian/images/xiaolian.png" alt="" />
  <input type="text" id="msg" value="" maxlength="300">
  <p style="background: rgb(17, 79, 142);" id="sendBtn">发送</p>
 </div>
 <!-- 底部 end-->
</body>
</html>
<script src="http://apps.bdimg.com/libs/jquery/2.1.4/jquery.min.js"></script>
<script src="https://cdn.bootcss.com/layer/3.1.0/layer.js"></script>
<script type="text/javascript">
$(function () {
 var uid = 666;//当前用户id
 var token = 'abcdefg';//用户token
 
 //判断浏览器是否支持WebSocket
 var supportsWebSockets = 'WebSocket' in window || 'MozWebSocket' in window;
 if (supportsWebSockets) {
  //建立WebSocket连接(ip地址换成自己主机ip)
  var ws = new WebSocket("ws://127.0.0.1:9501?uid="+uid+"&token="+token);
  ws.onopen = function () {
   layer.msg('服务器连接成功',{shade:0.1,icon:1,time:600});
  };
  ws.onerror = function () {
   layer.msg('服务器连接失败',{shade:0.1,icon:2,time:600});
  };
  ws.onmessage = function (evt) {
   var data = $.parseJSON(evt.data);
   //错误提示
   if(data.status != 1){
    layer.alert(data.message,{icon:2});
    return;
   }
   //消息返回
   if (data.status==1 && data.data.message!='') {
    var html = "";
    if (data.data.uid == uid) {
     html += "<div style='word-break:break-all' class=\"show\"><div class=\"time\">"+data.data.post_time+"</div><div class=\"msg\"><img src=\""+data.data.head_img+"\" alt=\"\" /><p><i clas=\"msg_input\"></i>"+data.data.message+"</p></div></div>";
    }else{
     html += "<div style='word-break:break-all' class=\"send\"><div class=\"time\">"+data.data.post_time+"</div><div class=\"msg\"><img src=\""+data.data.head_img+"\" alt=\"\" /><p><i clas=\"msg_input\"></i>"+data.data.message+"</p></div></div>";
    }
   }
   $(".message").append(html);
   setTimeout(function () {
    ($('.message').children("div:last-child")[0]).scrollIntoView();//向上滚动
   },100);
  };
  ws.onclose = function (res) {
   
  };
  //按钮发送
  $("#sendBtn").click(function () {
   var contents = $("#msg").val().trim();
   if(contents == null || contents == ""){
    layer.msg('内容为空',{shade:0.1,icon:2,time:600});   
    return false;
   }else{
    ws.send(contents);
    $("#msg").val("");
   }
  });
  //回车发送
  $("#msg").keydown(function (evel) {
   var that = $(this);
   if (evel.keyCode == 13) {
    evel.cancelBubble = true;
    evel.preventDefault();
    evel.stopPropagation();
    var contents = that.val().trim();
    if(contents == null || contents == ""){
     layer.msg('内容为空',{shade:0.1,icon:2,time:600});    
     return false;
    }else{
     ws.send(contents);
     that.val("");
    }
   }
  });
 }else{
  layer.alert("您的浏览器不支持 WebSocket!");
 }
});
</script>

服务器移到项目根目录开启服务:

php public/index.php Websocket/start

这里的路径,是因为我绑定了home模块为默认模块,tp5默认情况是:php public/index.php index/Websocket/start)

开启成功,查看端口已经被监听:

lsof -i:9501

很多PHPer在进阶的时候总会遇到一些问题和瓶颈,业务代码写多了没有方向感,不知道该从那里入手去提升,对此我整理了一些资料,包括但不限于:分布式架构、高可扩展、高性能、高并发、服务器性能调优、TP6,laravel,YII2,Redis,Swoole、Swoft、Kafka、Mysql优化、shell脚本、Docker、微服务、Nginx等多个知识点高级进阶干货需要的可以免费分享给大家 ,需要 请戳这里

总结

以上所述是小编给大家介绍的PHP框架实现WebSocket在线聊天通讯系统,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对三水点靠木网站的支持!
如果你觉得本文对你有帮助,欢迎转载,烦请注明出处,谢谢!

PHP 相关文章推荐
分享PHP入门的学习方法
Jan 02 PHP
php面向对象全攻略 (六)__set() __get() __isset() __unset()的用法
Sep 30 PHP
PHPnow安装服务[apache_pn]失败的问题的解决方法
Sep 10 PHP
md5 16位二进制与32位字符串相互转换示例
Dec 30 PHP
使用PHP实现阻止用户上传成人照片或者裸照
Dec 25 PHP
php从完整文件路径中分离文件目录和文件名的方法
Mar 13 PHP
php生成无限栏目树
Mar 16 PHP
thinkPHP5 ACL用户权限模块用法详解
May 10 PHP
Laravel中Facade的加载过程与原理详解
Sep 22 PHP
Laravel框架使用Seeder实现自动填充数据功能
Jun 13 PHP
PHP数字金额转换成中文大写显示
Jan 05 PHP
PHP+Ajax简单get验证操作示例
Mar 02 PHP
PHP读取Excel内的图片(phpspreadsheet和PHPExcel扩展库)
Nov 19 #PHP
使用PHP开发留言板功能
Nov 19 #PHP
关于Laravel参数验证的一些疑与惑
Nov 19 #PHP
php传值和传引用的区别点总结
Nov 19 #PHP
php 使用 __call实现重载功能示例
Nov 18 #PHP
PHP中通过getopt解析GNU C风格命令行选项
Nov 18 #PHP
php 多继承的几种常见实现方法示例
Nov 18 #PHP
You might like
解析php中如何调用用户自定义函数
2013/08/06 PHP
简单介绍PHP非阻塞模式
2016/03/03 PHP
基于JQuery的一个简单的鼠标跟随提示效果
2010/09/23 Javascript
深入理解JavaScript系列(4) 立即调用的函数表达式
2012/01/15 Javascript
如何让easyui gridview 宽度自适应窗口改变及fitColumns应用
2013/01/25 Javascript
获取元素距离浏览器周边的位置的方法getBoundingClientRect
2013/04/17 Javascript
JQuery.get提交页面不跳转的解决方法
2015/01/13 Javascript
jQuery前端分页示例分享
2015/02/10 Javascript
jQuery ui实现动感的圆角渐变网站导航菜单效果代码
2015/08/26 Javascript
非常棒的jQuery图片轮播效果
2016/04/17 Javascript
微信小程序引用iconfont图标的方法
2018/10/22 Javascript
JS+HTML5 canvas绘制验证码示例
2018/12/05 Javascript
详解vue-cli+es6引入es5写的js(两种方法)
2019/04/19 Javascript
详解VScode编辑器vue环境搭建所遇问题解决方案
2019/04/26 Javascript
使用 Angular RouteReuseStrategy 缓存(路由)组件的实例代码
2019/11/01 Javascript
[04:07]显微镜下的DOTA2第八期——英雄复活动作
2014/06/24 DOTA
Python高级应用实例对比:高效计算大文件中的最长行的长度
2014/06/08 Python
Python Unittest自动化单元测试框架详解
2018/04/04 Python
Python 实现选择排序的算法步骤
2018/04/22 Python
postman传递当前时间戳实例详解
2019/09/14 Python
Python列表list常用内建函数实例小结
2019/10/22 Python
Python3和PyCharm安装与环境配置【图文教程】
2020/02/14 Python
Python tkinter实现简单加法计算器代码实例
2020/05/13 Python
使用opencv识别图像红色区域,并输出红色区域中心点坐标
2020/06/02 Python
Python中的全局变量如何理解
2020/06/04 Python
DataFrame.groupby()所见的各种用法详解
2020/06/14 Python
有abstract方法的类一定要用abstract修饰吗
2016/03/14 面试题
安全标准化汇报材料
2014/02/03 职场文书
医学专业毕业生求职信
2014/06/20 职场文书
焦裕禄精神心得体会
2014/09/02 职场文书
安全保证书
2015/01/16 职场文书
工作态度检讨书范文
2015/05/06 职场文书
硕士论文致谢范文
2015/05/14 职场文书
2015年政治教研组工作总结
2015/07/22 职场文书
2015年幼师个人工作总结
2015/10/15 职场文书
Python+Tkinter制作专属图形化界面
2022/04/01 Python