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实现查看邮件是否已被阅读的方法
Dec 03 PHP
php读取3389的脚本
May 06 PHP
php实例分享之mysql数据备份
May 19 PHP
php中eval函数的危害与正确禁用方法
Jun 30 PHP
PHP开发框架Laravel数据库操作方法总结
Sep 03 PHP
PHP中上传多个文件的表单设计例子
Nov 19 PHP
php制作文本式留言板
Mar 18 PHP
使用PHP+AJAX让WordPress动态加载文章的教程
Dec 11 PHP
PHP使用token防止表单重复提交的方法
Apr 07 PHP
php加密之discuz内容经典加密方式实例详解
Feb 04 PHP
PHP面向对象程序设计中的self、static、parent关键字用法分析
Aug 14 PHP
PhpSpreadsheet中文文档 | Spreadsheet操作教程实例
Apr 01 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中模拟POST传递数据的两种方法分享
2011/09/16 PHP
php使用array_rand()函数从数组中随机选择一个或多个元素
2014/04/28 PHP
php自动加载方式集合
2016/04/04 PHP
THINKPHP-Apache服务器中使用Alias虚拟目录URL重写 隐藏index.php
2021/03/09 PHP
使用EXT实现无刷新动态调用股票信息
2008/11/01 Javascript
flash遮住div问题的正确解决方法
2014/02/27 Javascript
javascript:window.open弹出窗口的位置问题
2014/03/18 Javascript
简单方法判断JavaScript对象为null或者属性为空
2014/09/26 Javascript
js调出上下文菜单的实例
2015/12/17 Javascript
JS延时器提示框的应用实例代码解析
2016/04/27 Javascript
AngularJS基础 ng-hide 指令用法及示例代码
2016/08/01 Javascript
DOM操作原生js 的bug,使用jQuery 可以消除的解决方法
2016/09/04 Javascript
js仿微信语音播放实现思路
2016/12/12 Javascript
vue 2.0路由之路由嵌套示例详解
2017/05/08 Javascript
vue src动态加载请求获取图片的方法
2018/10/17 Javascript
Nodejs监控事件循环异常示例详解
2019/09/22 NodeJs
浅谈vue 锚点指令v-anchor的使用
2019/11/13 Javascript
Vue extend的基本用法(实例详解)
2019/12/09 Javascript
JS代码实现页面切换效果
2021/01/10 Javascript
[01:16:37]【全国守擂赛】第三周决赛 Dark Knight vs. 一个弱队
2020/05/04 DOTA
python实现通过pil模块对图片格式进行转换的方法
2015/03/24 Python
itchat和matplotlib的结合使用爬取微信信息的实例
2017/08/25 Python
python使用tkinter库实现五子棋游戏
2019/06/18 Python
PyQt QCombobox设置行高的方法
2019/06/20 Python
如何使用python把ppt转换成pdf
2019/06/29 Python
python匿名函数的使用方法解析
2019/10/10 Python
利用三角函数在canvas上画虚线的方法
2018/01/11 HTML / CSS
最好的商品表达自己:Cafepress
2019/09/04 全球购物
精伦电子Java笔试题
2013/01/16 面试题
主键(Primary Key)约束和唯一性(UNIQUE)约束的区别
2013/05/29 面试题
答谢会策划方案
2014/05/12 职场文书
抗洪救灾标语
2014/10/08 职场文书
高考作弊检讨书1500字
2015/02/16 职场文书
详解vue中v-for的key唯一性
2021/05/15 Vue.js
利用python做数据拟合详情
2021/11/17 Python
Elasticsearch 聚合查询和排序
2022/04/19 Python